Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AnimationTree -> AnimationNodeStateMachinePlayback: travel/start from a specific position #9175

Open
artvel opened this issue Feb 25, 2024 · 5 comments

Comments

@artvel
Copy link

artvel commented Feb 25, 2024

Describe the problem or limitation you are having in your project

I am having an animation that is visualizing a magical cast. The animation is 5s+ looping in a casting position type and after that it is visualizing the execution of the cast.

I would like to take the execution time(5.26) and run the animation like:

var startTime:float = executionTime - castTime
player.travel("myAnim", true, startTime)

I don't see how I could solve this in a smarter way right now besides cutting the animations perfectly so it fits to every ability cast time. That would be a lot of initial and maintenance work.

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

Having the start position parameter enables us to have some animation types and just match the start position without creating the same kind of animation multiple times with different timings.

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

void start(node: StringName, reset: bool = true, start_position:float = 0)
void travel(to_node: StringName, reset_on_teleport: bool = true, start_position:float = 0)

# Example:
var player: AnimationNodeStateMachinePlayback
player.start("myAnim", true, 5.26)
player.travel("myAnim", true, 5.26)

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

No

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

NA

@artvel artvel changed the title AnimationTree: travel/play from a specific position AnimationTree: travel/start from a specific position Feb 25, 2024
@artvel
Copy link
Author

artvel commented Mar 14, 2024

Just found another case that requires this feature.

If you have an AnimationTree that blends the same animation fully(while standing) and partially(while walking). You can't have a transition if you want to blend between fully and partially as you can't provide the start time.

So in other words, when you executed the animation fully while standing and while the animation is playing you started walking. You would want to take the current play time from fully and start playing partially from the same position.

@artvel
Copy link
Author

artvel commented Mar 14, 2024

Hey @jmarceno thanks for bringing up ideas. I just had a look at it and so far I don't see how to actually solve it. Maybe I am missing something.

This is how it looks:
Screenshot 2024-03-14 at 11 53 13

@artvel
Copy link
Author

artvel commented Mar 14, 2024

I would handle the transition through code as I have a movement state machine in gdscript.
So what I would do is when A started while in Standing state. I would check in the start of any moving state like Walking, Jumping or Falling if A is running. In case of true, I would call something like:

var current_play_time:float = lowerBody.get_current_play_position()
animation_tree.set("parameters/BlendCasts/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)
upperBody.travel("A", true, current_play_time)

If there is a better way of handling this, I'd love to here it.

@artvel
Copy link
Author

artvel commented Mar 14, 2024

Okay, thanks. I'll look into that.

About your point on the global TimeScale. I think, there are enough ways to handle the scale globally already. For example here:
Screenshot 2024-03-14 at 13 23 42

@artvel artvel changed the title AnimationTree: travel/start from a specific position AnimationTree -> AnimationNodeStateMachinePlayback: travel/start from a specific position Mar 14, 2024
@hsandt
Copy link

hsandt commented Jul 4, 2024

I have a different issue where I want to force play an animation node from the start, when traveling to the same node as the current node.

But that's relevant to this issue because it raises the question of whether start_position=0 should be considered like "keeping current state" (current behavior, so retrocompatible) or "force restart from zero" (what I need).

Real-world case: if hero damages enemy, enemy plays Hurt animation. Hurt animation automatically reverts to Idle at the end. But if hero damages enemy again right on the last frame of Hurt animation, AnimationTree Hurt animation will

Indeed, currently, if current playback node is A, and I travel to A, nothing happens. Unlike AnimationPlayer I cannot force play from 0 by calling stop first: AnimationNodeStateMachinePlayback.stop has a different meaning and will simply stop running the Animation Tree state machine, keeping the last state (last animation on its last frame) instead of reverting it to the first frame and acknowledging the next travel as a brand new animation to play. It seems that the very nature of travel makes it hard to tell it to replay the same node twice.

Inspired by AnimationPlayer play(&"RESET") + advance(0) hack (#6417), I tried other hacks such as:

state_machine.travel(&"Idle")
state_machine.next()
state_machine.travel(animation_name)
state_machine.next()

to no avail.

The only call that actually forced node change was start:

var last_animation := state_machine.get_current_node()
if last_animation == animation_name:
	# When already playing the same animation
	# (including when chaining from last frame)
	# we need to force restart (travel would not restart the animation
	# and unlike AnimationPlayer, stop only pauses so travel would
	# not work after stop either)
	state_machine.start(animation_name)
else:
	state_machine.travel(animation_name)

It's not that bad, but it needs an extra check on last animation (state_machine.get_current_node()) while a from_start flag would be explicit on what I want, and start_position=0 would also work, but when using a float there is no way to indicate that we want to preserve the last state (unless we encode start_position=-1 but I find it less intuitive).

Should I make a different issue to suggest either a parameter or different method restart to force play the same node from the start, then?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants