godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.13k stars 93 forks source link

Better way of handling one shot action animations #5155

Open Rytelier opened 2 years ago

Rytelier commented 2 years ago

Describe the project you are working on

An action 3D game

Describe the problem or limitation you are having in your project

I'm facing a problem with playing action animations, like attack, dodge, stagger, etc. The AnimationTree doesn't have functionality to have it handled in simple and smooth way, I have to use workarounds. First - all common solutions were not suitable for my needs.

What I settled on is one OneShot node where the animation in the AnimationNodeAnimation is replaced in a script. Script checks if animation ended by checking the active parameter. Then faced problems that needed to be worked around:

Problem: I faced is that when chaining action animations, where next one plays in middle of current, there would be no smooth transition. Workaround: added another animation node and blend2 node, and made action animations switch the active node, where blend2 node would smoothly blend transitions through a script. Screenshot 2022-08-13 120630

Problem: animation events would stack from the second node even though it wasn't enabled by blend (that's when chain sequence is starting, where animation start from first frame). Workaround: make an empty animation clip that is couple seconds long and add it to the inactive action node.

Problem: when calling an action right at the end of animation, the OneShot node would just go disabled when setting the seek position, making whole action canceled. Workaround: adding a delayed call that forced the one shot node to go active again.

It was all hard to figure out, as the tree doesn't provide simple functions to suit my approach of actions.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Solution #.1: State tree based actions

animTree.Play(string path, float crossfadeTime)

Either something like override void OnNodeEnter (attached to the node) or a signal

Solution #.2: Add dynamic animation node.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

State machine controlled actions: Screenshot 2022-08-13 120808 Dynamic animation node: similar structure as OneShot except has additional functionality I mentioned above.

If this enhancement will not be used often, can it be worked around with a few lines of script?

As mentioned before, the workaround is complicated.

Is there a reason why this should be core and not an add-on in the asset library?

It will help with clean animation tree setup with straightforward actions instead of having messy solutions or workarounds.

TokageItLab commented 2 years ago

Which version of this are you using? I made a modification to some Nodes when I added sync recently (https://github.com/godotengine/godot/pull/62623), so it may be that workaround using Oneshot or Transition is working.

TokageItLab commented 1 year ago

Now StateMachine play() teleports to any state. The remaining problem is that there is no crossfade, but I think that problem can be solved in the following way:

Provide only two Attack States. Connect them to the normal State. This should look like a triangle.

At the start and end of the attacking combo, the combo should go back and forth between the Normal State and the Attack State.

During the combo, the animation should loop between the two Attack States with changing dynamically assigned animations depending on the attacking action.