-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Allow AnimationStateMachine / AnimationNode to restart when transitioning to the same state #71418
Conversation
e605d12
to
9685429
Compare
Works, but crashes whenever I select the AnimationPlayer node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've had a chance to sit down with this properly now, and I think it's fine. The only thing I would still potentially recommend changing is the name of the 'interrupt' which I think might be too generic and could mean other things depending on the context. My current recommendation is changing it to the more literal 'skip_to_next_state'.
@SaracenOne I get the feeling that "skip" is going to ignore xfade. So how about the following:
|
9685429
to
cc1f489
Compare
For now, I renamed |
cc1f489
to
e480262
Compare
This looks mostly good to me, would be good to agree a proper name with @SaracenOne before merging |
@@ -342,12 +342,17 @@ void EditorPropertyTextEnum::_notification(int p_what) { | |||
} | |||
|
|||
EditorPropertyTextEnum::EditorPropertyTextEnum() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to explain what this is for. Maybe some example screen of the change to show the problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, wait a second, there are screens that can be broken by it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r_list->push_back(PropertyInfo(Variant::BOOL, active)); | ||
r_list->push_back(PropertyInfo(Variant::BOOL, prev_active, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE)); | ||
r_list->push_back(PropertyInfo(Variant::BOOL, active, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_READ_ONLY)); | ||
r_list->push_back(PropertyInfo(Variant::INT, request, PROPERTY_HINT_ENUM, ",Fire,Abort")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first one has no name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I'm not familiar enough with the API to say what would make sense but UX wise it doesn't seem immediately obvious why there's an empty drop down list, and what the empty option does compared to the other two.
But I trust your judgment on this. Can always be improved later on if users do report this as confusing :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this looks good to me!
Thanks! |
How do I trigger a Fire or Abort request on a OneShot node in the code?? |
It has been described in the description. The document(tutorial) for AnimationTree is overall out of date and needs to be updated later. # Property for the transition state requests. It will be cleared immediately in the next animation tree process.
anim_tree["parameters/OneShotNode/request"] = AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE
anim_tree["parameters/OneShotNode/request"] = AnimationNodeOneShot.ONE_SHOT_REQUEST_ABORT
anim_tree.set("parameters/OneShotNode/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)
anim_tree.set("parameters/OneShotNode/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_ABORT)
print(anim_tree["parameters/OneShotNode/active"]) # Read-only. |
Why can't we just say "Fire" instead of AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE? This is making things more complicated. It's also inconsistent with Transitions where you can set the state parameter via a string... |
Transition has a clear list of strings, but OneShot uses just an Enum as an Int for the request. |
Any way of checking if StateMachine is already in a given state so not to restart the animation when using travel() to the same state? Maybe the travel() function could have a second parameter (restart = true, false) to avoid restarting so to resemble the previous behavior. Or maybe is about documentation. |
if state_machine_playback.get_current_node() != "A":
state_machine_playback.travel("A") |
If there is a long crossfade, it may have already moved to the next state, and we may be better to expose the |
There is also a second argument, reset_on_teleport, but if it is false, it would certainly make more sense not to restart with travel. I thought I had implemented it that way, but there seems to be some problem and it is not working. I will fix it later. |
@jcarlosrc I sent #71840. With that, you can write: state_machine_playback.travel("A", state_machine_playback.get_current_node() != "A") It does not allow its own restart. But it allows teleports and resets from other states. Note just that the existing travel path is to be discarded. In order to keep the existing travel path, if statement must be used. |
Closes godotengine/godot-proposals#5965
Fixed #69570
Fixed #69382
Fixed #71195
Allow AnimationStateMachine / AnimationNode to restart when transitioning to the same state. Also, allow NodeTransition to use String values.
Containing #71264. At first I was working with it as same PR #71264, but a few fundamental modifications caused break compatibility, so I separated this PR.
StateMachine
Make it restart when it tries to travel() to the same state. This can be resolved with one line change.
NodeTransition / NodeOneShot
For this, there was a problem with the original implementation, and 2 fundamental modifications are necessary.
1:
Currently they detect state changes by whether the property has changed from the previous frame, but this does not allow changes to the same state.
This means that they need an independent property as a request, like a StateMachine. So, implement the following properties for state changes.
NodeTransition:
NodeOneShot:
In addition, since there was only one
active
flag, there was no way to stopauto restart
from the property, but nowauto restart
is stopped by an abort request.2:
Some properties need to be changed only by request to prevent to make broken state, but the current status should be retrievable, so it should be PROPERTY_USAGE_READ_ONLY, not PROPERTY_USAGE_NONE.
However, the entity of the AnimationNode property is stored in the AnimationTree's map. During playback, the AnimationNode fetches the properties from the map, which means that read-only cannot be set using the USAGE flag.
Therefore, it is necessary to add a bool value to the AnimationTree map to implement read-only for the AnimationNode's parameter.
Video
Godot.2023.01.15.-.02.43.27.02.mp4
Godot.2023.01.15.-.02.43.27.03.mp4
restart_test.zip
If approved, I will update the document as soon as possible.