I'm making a 2D game. I have 50+ animations and some of them are very big, which means that some of them can exceed the 2048 x 2048 size limitbecause in order to animate a spritesheet we have to keyframe the frame property + HFrames and VFrames properties, and that only works if our spritesheet has all frames of equal size so TexturePacker has to use the Grid/Strip algorithm without duplicate detection and 0 trimming (I care about the size of frames for setting specific sprite2d offsets). This makes the spritesheets enormous because of all the transparent space and duplicates. Is there any way to work with trimmed spritesheets at all in AnimationPlayer?
I know there is a TexturePacker plugin that creates individual .tres files from one atlas source, but this is for AnimatedSprite2D + the individual .tres files are increasing scene size a lot quite fast.
I even tried loading .tres files as texture of sprite2d and keyframing the texture property every frame in AnimationPlayer, but like I said this increases the scene size a lot.
Is there an official way to do this? Any plugins? Something that can read the data file and determine where the frames are located at and what was their original position/rotation etc
Have you tried adapting the plugin code yourself to store .res files in stead of .tres files?
I think you could just strip the letter t from the file nameā¦
What would probably be better is to simply have a custom script parse this data file (seems well documented) and store the images in memory as separate ImageTexture, right? Or maybe divide up the sheets a little (if that is faster for the GPU)
The format looks well documented, can you try to write it yourself?
If I had time and focus now I mightāve offered to set you up with something. But sorry, at the moment thatās not an option.
Just to satisfy curiosity: try and see if you can modify the existing plugin yourself firstā¦
That would only reduce the .tres file size on disk but it wouldnāt reduce the runtime memory usage. The tres files are also only like 1kb each so the extension/format isnāt the core issue here. The texture packer plugin creates individual AtlasTexture resources and the only way to animate a sprite2d with these as far as i know is to keyframe the texture property every frame, which is bad practice I think. Ideally there should be a way to keyframe AtlasTexture once at the beginning, and then only keyframe the region and margin properties
Oh, I thought you meant you wanted AnimatedSprite2D by this:
My bad.
Iām sorry. At the moment I only have my phone with me, so I canāt verify that these properties can indeed not be updated on a property track via key frames. Because my assumption would be that it should be totally possible.
Have you tried?
If that really is impossible, you can still create a method track that invokes a script method, letās call it progress_to_next_frame() that reads out a custom resource that holds the correct texture region info per frame per animation and then sets the AtlasTexture region from there.
If you make it a @tool script you can test it while editing as well.
The import data file parsing code you could cherry pick from the plugin to create your custom metadata Resource with so you wonāt have to start from zero..
Again, just hallucinating this on my phone as if Iām an LLM here.
Will you then still need to address the biggest sheets? Because you could read them out and divide those in code as well, Iām guessing, although that would also mean having to adapt this custom region metadata Resource to your Division as well.
We are creating the .tres files because this seems to be the best option to make the sprites available inside Godot. But you are right ā it is maybe not ideal for importing lots of animations.
Iāve experimented with extending our TexturePacker importer plugin: we can easily create an AnimationLibrary per sprite sheet (e.g. .animations.tres) containing a keyframe animation for each sequence. Each animation does exactly what you described ā the AtlasTexture is set up once on your Sprite2D, and the keyframes only change its region and margin (plus atlas, so multipack sheets work ā which also solves your 2048Ć2048 limit, since a sequence can span multiple texture pages).
You then create a Sprite2D, add a child AnimationPlayer, load the generated library, and play the animations. Nothing is embedded in your scene files ā itās one shared .tres per sheet.
Hereās a test version of the importer plugin (not yet released). It will be part of the next TexturePacker 8.2.0 release. Weāll also release an update of the plugin with it.
Plugin
You have to add this exporter to TexturePacker:
How to use it:
In TexturePacker, enable Auto-detect animations in the data-file settings. Sprites whose names end in a frame number (e.g. run/RunRight_0001.png ⦠RunRight_0006.png) are grouped into animation sequences and written to the .tpsheet.
Publish into your Godot project. The importer plugin picks up the sheet and generates .animations.tres ā an AnimationLibrary with one looping 10 fps animation per sequence. Each animation keyframes the atlas, region and margin of a single AtlasTexture, so trimmed sprites play with the correct size and offset, and multipack sheets work too.
In your scene: add a Sprite2D and assign it an AtlasTexture (make it unique ā the animation modifies it). Add an AnimationPlayer as a child of the Sprite2D and set its Root Node to ā¦
In the AnimationPlayer choose Manage Animations⦠ā Load Library and load .animations.tres under the empty library name.
Play an animation, e.g. $Sprite2D/AnimationPlayer.play(āCharacter-run-right-RunRightā).
Loop mode and speed you change in the Godot editor are kept when the sheet is re-imported.
Feedback welcome.
The problem I am currently facing: After loading the animations into the player, they do not get updated⦠e.g. when adding sprites or changing the sprite sheets, animations are invalid.
Ok - It seems I found a fix for the reload problem.
Iāve also optimized the keyframes to not create duplicate keyframes - e.g. if the texture does not change.
However I get this error: āERROR: res://addons/codeandweb.texturepacker/texturepacker_import_spritesheet.gd:160 - Invalid access to property or key āfilenameā on a base object of type āDictionaryā.ā for multiple lines
One more thing. This requires the AnimationPlayer to be a child of the sprite itās going to animate as far I understand. But if I have multiple sprites I want to animate at the same time in the same AnimationPlayer, it becomes problematic. Would it be possible to change the behavior (or add as an option) to for example drag the .tres onto sprite2d texture, keyframe it once in AnimationPlayer and then keyframe the region and margin properties manually? Basically the flow would be similar to how godot lets you animate the āFrameā property by setting hframes and vframes, but we would be keyframing region and margin. Basically I would love to have manual control somehow so that I can create the animation myself and keyframe things myself for a specific sprite2d. Manual control is also important for me because then I can set the FPS and keyframe accordingly. In my current animations Iām animating player body sprite, player head sprite, weapon layer, gunfire
The AnimationPlayer doesnāt need to be a child of the sprite. What matters is its Root Node. The generated tracks use .:texture:region, where . means āthe Root Nodeā, so the player can sit anywhere as long as Root Node points at the sprite. Child-of-the-sprite is just the arrangement that needs no setup, since Root Node defaults to ⦠Our docs were unclear here and Iāve fixed them.
Youāre still right that this doesnāt cover your case. An AnimationPlayer has one Root Node, so a generated animation drives one sprite. For body + head + weapon + gunfire, the generated AnimationLibrary is the wrong tool.
What you want already works, and needs less setup than youād expect. You donāt have to keyframe region and margin by hand, and you donāt need to reparent anything. The importer already writes one AtlasTexture per sprite into .sprites/. Keyframe the texture property with those:
Add an AnimationPlayer anywhere above your sprites. In most rigs you can leave Root Node alone ā the default .. is its own parent, and node paths are resolved from there, so sprites nested further down are reachable too.
Add one value track per sprite, using its path from the Root Node: Body:texture, Head:texture, or Rig/Weapon:texture if it sits deeper.
Set each trackās update mode to Discrete.
Drag the .tres for each frame from .sprites/ onto the track where you want it.
This is the hframes/vframes + frame flow you had in mind, except each key holds a whole AtlasTexture. Trimmed sprites still land correctly, since each one carries its own region and margin.
You get everything you asked for: your own frame rate, all four sprites on one timeline, and full manual control ā including holding a frame longer than the rest, which the generated animations canāt express.
Iāve added this to the plugin README as āAnimating several sprites in one AnimationPlayerā.
I would like to create the new release for this version of the TexturePacker Importer.
The add-on in TexturePacker will be released later today or tomorrow.