godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Expose missing AnimationNodeStateMachinePlayback to scripting to allow serialization #7885

Open SaracenOne opened 1 year ago

SaracenOne commented 1 year ago

Describe the project you are working on

3D VR online virtual worlds application.

Describe the problem or limitation you are having in your project

The AnimationTree, but more specifically, the AnimationNodeStateMachine, currently relies on an internal resource called AnimationNodeStateMachinePlayback to keep track of certain state, including travel paths, state transitions, and playback position. This resource, however, does actually expose all of internal variables to scripting, and doesn't expose any of them to writing. As a result, if a game requires precise savegame serialization, such a heavily state-machine driven gave, it cannot reliably save and restore the data required to accurately reconstruct the exact properties of a working AnimationNodeStateMachine.

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

The simplest solution is to expose this to the scripting API, though this might also invite broader re-evaluation of some of the internal of how animation state is tracked, but one way or another, there needs to be a way accessing the full playback state so accurate serialization can be performed.

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

It would simply involve new functions added to the AnimationNodeStateMachinePlayback resource to allow both read and write access to these hidden properties.

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

Since there is currently no way via scripting to access the full internal playback state of an AnimationNodeStateMachine, engine changes are required in order to make this happen.

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

See above.

TokageItLab commented 1 year ago

I can agree with exposing some of the internal properties about AnimationNodeStateMachinePlayback, but I think there are a few properties that need to be readonly for state safety.

However, I think it will be difficult to do things like save the state itself if we can't rewrite it, so some properties will only have a getter, and when you want to set them, you will need to go through a higher level setter that requires a structure or some properties.

For example:

StringName get_prev_node();
// void  set_prev_node(StringName p_node); // This should not exist because it could break the state.

// The prev_node should only allow setting through an API that guarantees such a safe state.
void set_prev_and_current(StringName p_prev, StringName p_current, real_t p_progress);

May be related with https://github.com/godotengine/godot/pull/77347. @Daylily-Zeleen Also you might be interested.

mauriciomarinho2 commented 8 months ago

This would be highly appreciated, I'm working on a weapon system similar to the souls series, where each one loads it's own set of animations. The easiest and more maintainable way to achieve that, is to be able to save and load the AnimationNodeStateMachine or AnimationNodeStateMachinePlayback, which to my surprise it can't be done due to it being readonly. Saving the playback writes an empty file, as for the StateMachine, it does save a file, though I would have to write a parser for it to be useful, double click doesn't open it in an editor panel as expected with resource types.

Looking into nested StateMachines, it could work, but it would eventually become hard to maintain a giant mess of statemachines: Screenshot from 2024-03-10 15-33-31

For each animation set added, I would have to manually add their state machines on this giant list, instead of save it with it's weapon, or saved to a resource shared by multiple ones.

I have a system in place for items, that use an AnimationNode, they have a StringName attached with the name of the animation they use, when loaded into an item slot, the AnimationNode "animation" property is changed to the one the item requests.

Screenshot from 2024-03-10 15-36-27 "firebomb" selected, UseItem.animation becomes "throw" "healing" selected, UseItem.animation becomes "drink"

Although it uses strings to change the animation and it's not ideal, it works, doesn't break the system if I do a typo. Would be useful to do the same with StateMachines, author their .tres resources in editor, which they can't do right now, then load the appropriate one at runtime.