godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.1k stars 21.15k forks source link

Frame by frame animations on AnimationPlayer are a pain to deal with. #12469

Closed aaronmzn closed 4 years ago

aaronmzn commented 6 years ago

(changed the title from "AnimatedSprite, this should be its real purpose." so this issue is focussed on animations)

As a pixel artist, for frame by frame animations I prefer changing the Frames per second (fps) value like in AnimatedSprite or the animation speed with a Duration per frame (milliseconds) value like in Aseprite (even better)

AnimationPlayer is not meant to be used for sprite animations, but it has the amazing keyframing feature, so you have to use it regardless of how painful it is to use for sprite animations.

in other way AnimatedSprite IS meant for frame by frame animation, but its only purpose is for separated texture animations.

AnimatedSprites should be focused only for frame by frame animations and AnimationPlayer for what was made for, cutouts animations and tweening.

This is what I suggest for AnimatedSprites:

this way you don't have to deal with the AnimationPlayer timeline, moving keyframes and changing steps and lenght values.

This is an issue I'm sure a lot of people has and I hope this get added in a future stable version. like on 2.1.5

I already opened a issue about this a long time ago but didn't got much attention.

Zylann commented 6 years ago

Just a detail:

in other way AnimatedSprite IS meant for frame by frame animation, but its only purpose is for separated texture animations.

The UI seems to imply this, but it isn't true. You can use AtlasTextures too (which are just referring to a sub-rectangle in the same texture). But other than that I agree the workflow of this UI isn't the best when your animation is a pixel-art spritesheet with all frames in a grid, because it's tedious to create every single AtlasTextures with it. Godot is general-purpose though, so it might better suite the case where not all frames have the same size...

I think the workflow for which it was designed for was that you would make all frames in individual textures, and if you want an atlas for performance, Godot would convert all of them into AtlasTextures automatically on export. But as you say it would miss other AnimationPlayer features like triggering other actions or properties for each frame.

But other than that, I never really understood how AnimatedSprite is better. I never had to use it. I still just have all frames of my character in a grid, use a Sprite, and choose the frame with AnimationPlayer, which ends up being faster work than AnimatedSprite even if I don't use tweening. And it lets me benefit from all features it has, including speed, keyframing and frames with longer length (ripple-editing would be nice to add though!). No need to even add frames one by one, it also work if you put two keyframes with initial frame and final frame number. I even use multiple AnimationPlayers because the sprite and other nodes of my character can do things independently from each other, and that would be impossible with an AnimatedSprite. So my feeling is that AnimationPlayer is the most feature-complete animation system, you can do anything with it, but because it is so general-purpose, it's harder if you animate something more specific.

this way you don't have to deal with the AnimationPlayer timeline, moving keyframes and changing steps and lenght values.

But you are still dealing with a timeline, because it's an animation, with frames that you say can be of variable duration, and you even want keyframing. Sounds like you mostly want a new UI, which basically remaps to AnimationPlayer features.

groud commented 6 years ago

Personally, I think that, at a given point, we should be able to merge the AnimatedSprite editor within the animation editor. Maybe with a special kind of line in the animation editor. This would allow a more flexible work flow.

ghost commented 6 years ago

Sprite sheet support (all frames in one texture) like how Sprite node does

But, this kind of defeats the purposes of the AnimatedSprite as I always thought it was for a list of single sprites that could be animated. As Zylann said, the animationplayer with setting h,v rows, then animating the frame number creates this effect.

aaronmzn commented 6 years ago

(I changed the Title of this issue so this is more about animation and not about the node itself)

sorry if I don't explain myself well, English its not my language.

yeah, maybe its true, AnimatedSprite has its own purpose to have multiple separated images so they can be animated, but what if it was called Something like "SeparatedSprites" where you load all the images there then you can keyframe the frames like Sprite node does, or even combine them both?

The main reason if this thread if actually about the animation, and the idea was making AnimatedSprites just for this kind of animations so you don't have to use AnimationPlayer since its too complicated to this job.

now why is that about AnimationPlayer? let me explain, as the experience I had using this engine a couple of months for a game jam.

Changing the animation speed, the main problem I had with the workflow of AnimationPlayer and sprite animation.

lets say I have a 8 frames animation and you add a new AnimationPlayer node, you change the Lenght (0.8) and Steps (0.07) so it has the best flow between frames. At this point if you're happy with the speed of the animation then that's it, you're good, there is nothing else to do. animationplayer ui 1

but what if I want the animation to go a bit faster? that's where the tedious job beggins. I have to change the Lenght and Steps value, then move the keyframes again so it loops right and doesn't have an off time loop animationplayer ui 2

And you may say there is no need to do every frame, with first and last frame is enough with countinuous option set on, yeah a bit better, but still you have to change Lenght and Steps values then put the last frame on the second last step so AnimationPlayerd doens't jump over the last frame. animationplayer ui 3

But you are still dealing with a timeline, because it's an animation, with frames that you say can be of variable duration, and you even want keyframing. Sounds like you mostly want a new UI, which basically remaps to AnimationPlayer features.

Yes, a new UI for this kind of animation, a simplier one. Now let me explain myself, yes, you are still dealing with a timeline, but you are dealing with the AnimationPlayer timeline, they will work differently, AnimationPlayer works with Steps and Lenght and the timeline is like a ruler, and AnimatedSprite works just by a Frame Per Second (FPS) value and the animation's frames number that you add in the animation, the timeline is just a row of boxes where the boxes are the frames.

Leaving that aside, the keyframes will be triggered when a specific frame starts, lets say for a crouching animation the animation has 6 frames in total, you will work with only those number of frames, and on the in frame number 3 there will be a body shape resize only when the frame begins so when the animation reach the frame number 3 then it will trigger that body shape resize. there is no curve, easing or smoothing between frames, just a flat changing values from from 10 to 5.

to have a better Idea, lets take a look at the Aseprite's UI as an example aseprite timeline ui 1

now if the frames worked on milliseconds per frame (like on Aseprite, a duration for each frames) instead of frames per seconds then things can get more dynamic with the animations, as you can see in the picture above in the frames properties window, you can change the frame duration for all the frames with a single window, but you could edit the properties of any individual frame and change its duration, why is that? so you could do things like this. (left has individual duration in some frames and right doesn't) sidesattacksidesattack2 now you may say, this is something you can do with AnimationPlayer, yeah you can, but in this case you know what duration value each frame has just by right clicking it or something else, instead of guessing wich lenght/step value is the best while moving the keyframe on the timeline between steps. always tweaking, for every single sprite animation on the game, slowing you to continue doing other stuff.

Now one amazing aditional feature about this is that, either with FPS or Miliseconds Per Frame, you can do stuff in code like slowly increase the speed of the animation while the character is picking speed ingame like on Sonic 2d games, or in a rpg game where you increase the attack speed, you can also increase the animation speed( you can't change the animation speed in any way through code and either in Godot UI on the current godot version or 3.0 version, very disappointing)

I'm not saying AnimationPlayer its bad, its just its doens't have a great workflow for sprite animations, unless you don't care that much and you just want to see stuff moving.

AnimationPlayer can't be everything, its meant for cutout animations, tweening shapes, and oh I forgot the most important, 3D animation!

Possible Solutions

ghost commented 6 years ago

but what if I want the animation to go a bit faster? that's where the tedious job beggins. I have to change the Lenght and Steps value, then move the keyframes again so it loops right and doesn't have an off time loop

You can adjust the animation speed for that player in gdscript using anim_player.play("name", blend, speed) before u call each one ^^

If you check out the gbot tutorial github page he uses that methodology pretty extensively

aaronmzn commented 6 years ago

Oh... didn't knew about that, I guess thats new? I didn't bother to check again, my bad, sorry about that.

Well, that solves that part, it was really needed. Would be cool if that value can be changed in the UI for each animation and also have a preview in the editor.

AnimatedSprite has a get_frame() function where you can do much more dynamic animations like continue an attack animation after a certain frame has passed, I'm not very experienced with AnimationPlayer but I think you can do this triggering a function, right?

AnimatedSprite already has a UI for that, thats why I was bringing this node, it just need KeyFraming and Sprite node can do the Multiple texture support, so it can be focused only on this type of animations, most of the games on godot are 2d pixel art games or even just frame by frame animated sprites, so having a faster/easier UI would help the workflow, but I guess this UI isn't a priority for the devs right now. I just wish haha.

for me I can still use AnimationPlayer because I already know how to use it. but it was confusing at first.

ghost commented 6 years ago

I'm not very experienced with AnimationPlayer but I think you can do this triggering a function, right?

Should be able to. AnimationPlayer is really powerful with add function tracks,

You have a lot of good ideas and I love your enthusiasm! I used to be like that, slowly overtime, using Godot it just becomes part of life. Thing is, you will run into quirks (not saying to put Godot in a bad light, but saying this to show how flexible the engine is), that you can solve by brainstorming and not even delving into the source code. If you give your suggestions/issues some good thought (why your enthusiasm is so important), you will create solutions with built in nodes. This will allow you to finally transcend

metaphoricalsasquash commented 6 years ago

May I ask why this Issue has been closed? The main problem here is that AnimatedSprite does not have any of the much needed AnimatedPlayer features (like the use of Spriteatlas, a Call Method Track, Audio Playback track ect) and the AnimatedPlayer does not have the much needed features from the AnimatedSprite (ability to select the duration of each individual keyframe efficiently or change the duration of all keyframes during edit). I don't see how #18007 would fix this issue, even though if would be clearly an improvement. As a Sprite animator, I still could not use AnimatedSprite, because it lacks too many features I have in the AnimationPlayer.

Of course it may be possible to rework the AnimatedSprite until it becomes usable for anything more than the utmost rudimentary form of Sprite Animation, but adding a small feature to the AnimationPlayer instead seems far less effort to me: When selecting and dragging a Keyframe along the AnimationPlayer track, while holding Ctrl, all frames after that keyframe get pushed or pulled as many frames as the User is dragging and dropping the keyframe along the timeline.

This would essentially be the same as assigning a new duration value to a frame, which is a functionality every frame-by-frame animator needs. As a nice to have, it would be fantastic to have the possibility to set a frame duration for all keyframes within a track, which the Animator then can manually adjust or reset for fine tuning.

To set the duration of a keyframe right now, you have to make sure a all keyframes after are properly selected, there is always the danger of miss-clicking or missing one and having to do it all again, and with more complex animations or longer durations a lot of zooming and or scrolling in and out the timeline. It's really tedious and 95% of frame-by-frame animation work.

akien-mga commented 6 years ago

May I ask why this Issue has been closed?

You may, but the answer might surprise you :) screenshot_20180926_083623

metaphoricalsasquash commented 6 years ago

haha! I'm apparently still the noob around here.

piratesephiroth commented 6 years ago

@metaphoricalsasquash, AnimatedSprite does support AtlasTextures. You can pack your spritesheet using an external tool like TexturePacker and load each AtlasTexture as an individual frame with an importer plugin I think it's the only advantage it has over AnimationPlayer, which is better in every way but can only animate a sprite, which uses only a single texture that can be animated either with fixed size frames or manually cut regions.

That is unless we can use the AnimationPlayer to control an AnimatedSprite... I haven't tried that yet. EDIT: oh, dang, it actually works... issue solved?

image

metaphoricalsasquash commented 6 years ago

I would like to give this a try, do you know of any import plugins for open source spritesheet packers like the Sprite-Sheet-Packer? All info and tutorials I could find regarding Godot and spritesheet packing were on TexturePacker. But what's the point of working with an open source engine when I have to use propriety software to make a core aspect of 2D game dev like the use of spritesheets usable?

piratesephiroth commented 6 years ago

A few days ago I forked the TexturePacker importer and made a ShoeBox importer plugin. (ShoeBox isn't open source but it's free and uses the Adobe Air runtime so it runs on Windows and Mac, probably on Linux too.) I submitted it to the asset library but it still hasn't been reviewed.

EDIT: the software you mentioned can also export in the pixi.js format so it will work fine. EDIT2: I just changed it to pixijs spritesheet importer lol

https://github.com/piratesephiroth/shoebox-pixijs-spritesheet-plugin

SanchoPanza8000 commented 5 years ago

I'm not sure a TexturePacker really helps with underlying issues between AnimatedSprite and AnimationPlayer at hand.

I'm trying to use AnimatedSprites controlled by AnimationPlayer not even using spritesheets.. but individual, animated .png's. "Only" trying to get it somehow to work since about 40 hours. There is zero documentation for frame-animation. There's a few examples... but none of them go into different animations: Always a single kind of animation. When asking in help not enough people seem to be using this kind of animation as programmers probably just use some cutout sprites and stick to AnimationPlayer. I've set myself some workflow with other applications where I can decently animate something new and simple within 5 minutes or less. And I'm sure I'm not the only one who prefers NOT to directly animate in Godot if a different, more efficient pipeline is already setup. Please... do not enforce people to rigid workflows.. but enable them to use whatever they need. By: Enabling simple use of individual .pngs or Spritesheets in AnimatedSprites.. and letting those be controlled through AnimationPlayer. This is not about "enhacement". In the current state.. it seems impossible to actually use and get anything done. When I try to change the played Animation in AnimationPlayer... the only keyframed Animations played are actually the ones selected in "Animation" property of the AnimatedSprite. Having different animations in AnimatedSprites. Therefore completely has no effect. I am now forced to use a separate "AnimatedSprite" for each kind of animation. However that leads to all animations being shown on screen at once. This cumbersome workflow can't be intended by design: Especially since both AnimatedSprites and AnimationPlayer already have separate tracks for different animation-types... built... in.

reduz commented 5 years ago

Here are some Ideas I came up with, working with my students in these areas, let me know what you think.

Other than that, I am not sure if a lot more can be made. In Godot 3.1 editing these kind of animations is a lot more visually pleasant already (as frame previews are properly shown).

piratesephiroth commented 5 years ago

I'm not sure a TexturePacker really helps with underlying issues between AnimatedSprite and AnimationPlayer at hand.

Godot is a game engine, not 2d animation software. If you want to make complex animations then you should be setting them up with another specialized software then all you need is to import the final result into Godot.

AntimatedSprite is just a sprite that can accept multiple textures. That's its purpose and It's NOT meant to be used for complex animations by itself alone.

Maybe you're complaining about TexturePacker being paid but you have Shoebox and Spritesheet Packer that can do the same sprite packing and are free.

piratesephiroth commented 5 years ago

@reduz

A FPS/Seconds toggle button in animation editor snap box, so if you edit your frames by placing them in AnimationPlayer, you can see frames at any given FPS instead of seconds. This is just a snap visualization toggle though, changing it will not change your animation speed.

yeah, ideally we should be able to set the timing directly using frames instead of seconds but it would be already good enough just to have the option to display the time values converted to estimated frames

mrcdk commented 5 years ago

@DualMatrix has an open PR for that https://github.com/godotengine/godot/pull/22492

xaguzman commented 5 years ago
  • Add simple spritesheet support to SpriteFrames. If you create an animation within SpriteFrames, choose between single images or spritesheet.

This looks like a pretty clean solution to me

akien-mga commented 5 years ago

I think this might be solved in the master branch now, can anyone confirm?

frojo commented 5 years ago

Is this a dup of #9340 ? If not, what's the difference?

piratesephiroth commented 5 years ago

Is this a dup of #9340 ? If not, what's the difference?

The issue you mentioned only requests spritesheet support so it's been closed. This one requests 3 features, only one of them being spritesheet support.

Calinou commented 4 years ago

Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine.

The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker.

If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance!