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

[Proposal StateMachine] Add condition to transitions #19773

Closed
guilhermefelipecgs opened this issue Jun 25, 2018 · 9 comments · Fixed by #24402
Closed

[Proposal StateMachine] Add condition to transitions #19773

guilhermefelipecgs opened this issue Jun 25, 2018 · 9 comments · Fixed by #24402

Comments

@guilhermefelipecgs
Copy link
Contributor

guilhermefelipecgs commented Jun 25, 2018

Godot version:
8c7da84

OS/device including version:
Any

Issue description:

The current state machine doesn't have conditions for the transitions, so it is not possible to
control the transition of states from "environment" variables such as Unity or Unreal.

Unreal: https://docs.unrealengine.com/en-us/Engine/Animation/StateMachines/TransitionRules
Unity: https://docs.unity3d.com/Manual/StateMachineTransitions.html

My proposal is implemeting something simple, similar to the Unity.

Here is a prototype of what I was trying to do in godot:
captura de tela de 2018-06-25 17-33-19
The final version will be much bigger

Example of what I want to create in godot:
captura de tela de 2018-06-25 19-49-12

I've created my own state machine entirely on gdscript for my project and it looks like this:

# player.gd

onready var state_machine = preload("res://scripts/state_machine.gd").new($animation_player)

func _physics_process(delta):
	_apply_movement(delta)
	_apply_animation()

func _apply_movement(delta):
	# All movement code goes here

func _apply_animation():
	# Here I just need to pass some variables to state machine,
	state_machine.lv = lv
	state_machine.left = left
	state_machine.right = right
	state_machine.down = down
	state_machine.is_on_floor = is_on_floor()
	state_machine.speed = SPEED
	state_machine.speed_run = SPEED_RUN
	state_machine.jump = jump
	state_machine.shooting = shoot
	state_machine.ledge_climbing = ledge_climbing
	state_machine.ledge_hanging = ledge_hanging
	state_machine.aim = aim
	state_machine.turn = false

	# All logic of my state machine will run here.
	# After the update(), my AnimationPlayer will play the correct animation.
	state_machine.update()

And I expect that node "StateMachine" works in a similar way.

The benefits of this IMO are that "movement" code gets simpler because I don't have to worry about which animation I should play (and in my case, I have so many states that it's very difficult to work with it without a state machine) and it's more easy to debug (my current SM is a bunch of code and I need to use draw.io to help me visualize when I'm making the states/transitions).

So...

  1. We'll need a way to specify variables when creating the state machine to later define these variables by code (like the example code above).

  2. All transitions will need a condition that will use these variables that we define to control when you need to move to another state.
    Real example of some transition condition to "Idle" state on my project: is_on_floor and abs(lv.x) == 0.

  3. I think it would be useful a way to see all conditions from incoming transitions just clicking in the state. Something like this:
    captura de tela de 2018-06-26 10-56-50

  4. Maybe transitions could be some kind of resource, that way, we can use the same condition several times. eg: Most of my states use the same condition when goes to "Idle". If item 3 could be implemented, We can just copy/paste the conditions.

  5. Right now, I can't select multiple states (useful to reorganize multiple states).

  6. In my game, I've created some "shortcut" states (eg: "Any state", "All aims") just to simplify, I think maybe this could be done in godot using Sub State Machines but I can't test it without the conditions.
    Something like this:
    captura de tela de 2018-06-26 11-17-52
    Example of Any State
    Instead of this:
    captura de tela de 2018-06-26 11-16-41

  1. Also, I liked this options below, especially the "At End". I implemented exactly the same thing on my state machine, this means that I will only accept the condition if the animation of the current state is over. I would like to preserve this behavior.
    captura de tela de 2018-07-06 11-11-17
@groud
Copy link
Member

groud commented Jun 26, 2018

The thing is that it makes the state machine usable for logic. And from what I understood @reduz wanted to keep the system simple, and only for animation things (else people are going to need hierarchical FSM and all other extensions). From what I understand transitions should be triggered from code, there's no real need to make them into the state machine system itself.

I don't say it's bad, but it might go in the worng direction regarding @reduz original idea.

@guilhermefelipecgs
Copy link
Contributor Author

Well, the current state machine almost fits for what I need, it's all there, with a simple addition of conditions we can have more complex machines and IMO will be super cool to have this. At this moment, the machine only serves to very simple things, so simple that I almost see no advantage in it, it can be done by code. I think this simple change it's worth.

The thing is that it makes the state machine usable for logic. And from what I understood @reduz wanted to keep the system simple, and only for animation things

From my point of view, this is totally an animation thing.

From what I understand transitions should be triggered from code, there's no real need to make them into the state machine system itself.

I disagree, my first game prototype I was not using the state machine and it was very hard for me to control all this transitions, the movement logic was more complex because of this, when I've put all my animations on the state machine my problem was solved, my code now is much cleaner and simple.

@groud
Copy link
Member

groud commented Jun 26, 2018

Well, the current state machine almost fits for what I need, it's all there, with a simple addition of conditions we can have more complex machines and IMO will be super cool to have this. At this moment, the machine only serves to very simple things, so simple that I almost see no advantage in it, it can be done by code. I think this simple change it's worth.

The state machine handles blending between two states. Obviously for simple 2D things without blending needed it makes little sense.

From my point of view, this is totally an animation thing.

It's code inside the state machine editor, thus it is moving logic from script to the statemachine. Which makes this more than an animation only thing. Either we decide state machines should handle animation only or not, but adding this will definitely move more logic into the state machine, which i'm not sure is desired.

I disagree, my first game prototype I was not using the state machine and it was very hard for me to control all this transitions, the movement logic was more complex because of this, when I've put all my animations on the state machine my problem was solved, my code now is much cleaner and simple.

From what I understand, the statemachine here is not meant to replace the GDscript code. At least in the current design, both are needed. From what I understand it's only meant to deal with animation. So yeah, unless we are making state machines a more general purpose stuff (used for logic and all), your proposal just adds noise in something that, IMO, should be kept as simple as possible.

@groud
Copy link
Member

groud commented Jun 26, 2018

But regarding to the substate machines / transition from any state, this can probably be implemented.

@Riteo
Copy link
Contributor

Riteo commented Sep 22, 2020

I was bored and looked up the least updated issues. Isn't this kind of resolved by now?
I say kind of because there are conditions now, but not in the way proposed by OP. Still, shouldn't this issue be closed?

@MunWolf
Copy link
Contributor

MunWolf commented Mar 17, 2022

There is still one feature which would make the state machine easily controlable, currently you cant disable/enable different transitions by setting a condition animation_tree["parameters/conditions/land_hard"] that only works with auto advancement, it would be nice if we had a Disabled Condition as well as the currently implemented Advance Condition in AnimationNodeStateMachineTransition

@Riteo
Copy link
Contributor

Riteo commented Mar 17, 2022

@MunWolf wouldn't that just be part of the condition?

@MunWolf
Copy link
Contributor

MunWolf commented Mar 17, 2022

Not really?
The point of the Disabled property is to prevent auto advancement and travel, the current condition enables auto advancement.
Which means if you use the travel() method the state machnie can still travel to that state.
You can't really reuse the same condition for that as enabling auto advancement on a disabled node wouldn't do anything.

@guilhermefelipecgs
Copy link
Contributor Author

guilhermefelipecgs commented Mar 17, 2022

@Riteo not everything is resolved. advance_condition solves part of the issue.

Items 1 and 2 will be fixed by the advance_expression #54327
Item 3 and 4 I don't care about it anymore.
Item 5, 6 and other usability stuff will be fixed by this PR #24402

As I made a PR that after the merge closes this issue I didn't mind closing it after the advance_condition was implemented.

@akien-mga akien-mga added this to the 4.0 milestone May 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants