godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Animation Tree & State Machine: add method to access current travel request #10445

Open hsandt opened 4 weeks ago

hsandt commented 4 weeks ago

Describe the project you are working on

A platformer

Describe the problem or limitation you are having in your project

In my custom Animation Controller, I need to check if I have already told the Animate Tree State Machine to travel to a given node before doing it again. I am adapting code made for AnimationPlayer, which checks if new animation is same as animation_player.assigned_animation, to Animation Tree State Machine, but I find no equivalent.

For now I'm using state_machine.get_current_node() (AnimationNodeStateMachinePlayback::get_current_node) which tells me the current node, but if the state machine is currently traveling to node X, it will return all the intermediate nodes on the path A, B, C... giving me the illusion it's not moving toward X so I may call travel again for nothing (it doesn't restart travel fortunately, so it has no negative impact on game, but it messes up my debugging as my breakpoint would keep triggering).

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

I need a public method to access the current travel request. It would return empty StringName if there is none active at the moment. This way, I can first check the current travel request, and if none, fallback to checking get_current_node().

As a bonus, a hybrid method that does all that job would be nice: it would return the last node to travel to, which may either be the travel request if active, or the current node if last travel ended and reached target (or possibly if we directly started that node, forcing teleportation). But it's secondary once we're able to access travel request.

Note: it seems that start also launches a "start request" but since it should only take 1 frame, I'm not sure if it's worth checking.

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

Looking at source code scene/animation/animation_node_state_machine.cpp, it seems that StringName travel_request member is the one I'm looking for, and it is properly cleared on travel end/cancellation, so we could directly return it without having to check extra members like path.

I also see some start_request if we want an exhaustive method that checks travel request, start request and current node, but as explained above, start should be applied in 1 frame so I don't worry about comparing new node to a current node that would be outdated just for 1 frame.

So implementation could be:

// animation_node_state_machine.h
StringName get_travel_request() const;

// animation_node_state_machine.cpp
StringName AnimationNodeStateMachinePlayback::get_travel_request() const {
    return travel_request;
}

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

A workaround at GDScript level would be to manually store the travel request just after calling travel, in a custom member. In act, I'll probably do this for now.

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

This provides access to a private variable.

fire commented 3 weeks ago

@lyuma We discussed reviewing how animation tree works for usability