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

Add AnimationTree Advance Expressions #54327

Closed
wants to merge 1 commit into from

Conversation

reduz
Copy link
Member

@reduz reduz commented Oct 27, 2021

  • Allows specifying an expression as a condition for state machine transitions.
  • For this to work safely (user not call queue_free or something in the expression), a const call mode was added to Object and Variant (and optionally Script).
  • This mode ensures only const functions can be called, making it safe to use from the editor.
  • This also fixes usage in EditorSpinSlider (yes you can call queue_free() from it, I just realized).
  • Bonus: Fixed an animation import bug in Collada.

This gives much greater flexibility for creating complex state machines. By directly interfacing with the script code, it is possible to create complex animation advance condition for switching between states.

How it looks:

image

Tree it would apply to:

image

@reduz reduz requested review from a team as code owners October 27, 2021 22:31
@reduz reduz force-pushed the animtree-advance-expressions branch from 6a8d5c6 to c87065f Compare October 27, 2021 22:35
@reduz reduz requested a review from a team as a code owner October 27, 2021 22:35
@Calinou Calinou added this to the 4.0 milestone Oct 27, 2021
@Calinou
Copy link
Member

Calinou commented Oct 27, 2021

Out of curiosity, is there a property hint available in GDScript for exposing an expression hint in the inspector? This may be useful for people writing dialogue or level design-oriented add-ons.

@reduz
Copy link
Member Author

reduz commented Oct 28, 2021

@Calinou I think we auto parse those now, so doing export(Expression) var = "" should do.

* Allows specifying an expression as a condition for state machine transitions.
* For this to work safely (user not call queue_free or something in the expression), a const call mode was added to Object and Variant (and optionally Script).
* This mode ensures only const functions can be called, making it safe to use from the editor.
* Bonus: Fixed an animation import bug in Collada.

This gives much greater flexibility for creating complex state machines. By directly interfacing with the script code, it is possible to create complex animation advance condition for switching between states.
@David-Ochoa
Copy link

This is awesome and will help to solve some issues.
Is it possible to have a track of the improvements for the AnimationTree?
What I see could improve it:
a) Blackboard variables (a single list of all the variables referenced in the child nodes)
b) Allow to connect to self node (if I have an attack animation I need to stay attacking without passing by another state). Right now I'm connecting two equal nodes with an advance condition checking if I'm still attacking.
c) Allow to change a variable when animation ends (example: at end of equip/unequip allow to change IsEquiped variable)

@fire
Copy link
Member

fire commented Nov 7, 2021

This design purposely avoids the blackboard system by using the base node's variables. Which I think covers a, b and c.

a) Blackboard variables (a single list of all the variables referenced in the child nodes)
b) Allow to connect to self node (if I have an attack animation I need to stay attacking without passing by another state). Right now I'm connecting two equal nodes with an advance condition checking if I'm still attacking.
c) Allow to change a variable when animation ends (example: at end of equip/unequip allow to change IsEquiped variable)

@David-Ochoa
Copy link

This design purposely avoids the blackboard system by using the base node's variables. Which I think covers a, b and c.

a) Blackboard variables (a single list of all the variables referenced in the child nodes) b) Allow to connect to self node (if I have an attack animation I need to stay attacking without passing by another state). Right now I'm connecting two equal nodes with an advance condition checking if I'm still attacking. c) Allow to change a variable when animation ends (example: at end of equip/unequip allow to change IsEquiped variable)

That's great news. I'll download the dev build to give it a try.

@David-Ochoa
Copy link

image
I set this StateMachine with an advance condition IsAttacking (Attack is another StateMachine)
When I try to get the value the animation stops and don't recognizes the expression:
image
image

@David-Ochoa
Copy link

This design purposely avoids the blackboard system by using the base node's variables. Which I think covers a, b and c.

a) Blackboard variables (a single list of all the variables referenced in the child nodes) b) Allow to connect to self node (if I have an attack animation I need to stay attacking without passing by another state). Right now I'm connecting two equal nodes with an advance condition checking if I'm still attacking. c) Allow to change a variable when animation ends (example: at end of equip/unequip allow to change IsEquiped variable)

In the tests I did I cannot achive any of this points (read a StateMachine's variable, stay in the same node without duplicating it and update a variable in the StateMachine)

@David-Ochoa
Copy link

Godot4Test.zip
This is the project I was testing

@reduz
Copy link
Member Author

reduz commented Nov 20, 2021

@David-Ochoa I think you are misunderstanding what this does. The idea is precisely to not use variables in the animation tree but variables from your game script directly.

@David-Ochoa
Copy link

@David-Ochoa I think you are misunderstanding what this does. The idea is precisely to not use variables in the animation tree but variables from your game script directly.

I took time to make more tests and exporting a variable in a script works as a blackboard if a single script has all the variables and the script is assigned to the AnimationTree (using another node doesn't work and would make harder to test the AnimationTree):
image

Both other suggestions I made could be implemented with workarounds (changing the variable when animation finishes with a function call track and self connecting transitions duplicating the node).

As I mentioned, using other node than the AnimationTree for advance expressions will make difficult to test the AnimationTree in the editor because selecting the node to change the variable hides the AnimationTree.

@SaracenOne
Copy link
Member

SaracenOne commented Nov 28, 2021

Seems like it's on the right track! It already feels like it allows a significantly degree of cleaner code organisation for complex animation state machines. There's some usability issues with input of the actual expression field, and I'm kind of wondering if this would benefit for multi-edit, but that can be saved for another PR. I do think we need an equivilent system for blend trees though since it currently exists in a kind of half-way situation where different parts of the animation tree are driven in vastly different ways.

So far I've found two bugs with the system. The first I've already made a fix for which is that the button to self base expression node would be relative the current scene root rather than the animation tree V-Sekai@1b109ac

The second is that the expression editor seems to send its carat back to the first character when attempting to add spaces.

@joaopedrosgs
Copy link
Contributor

Any news on this?
Does it need more testing? I can test if necessary!

@rcorre
Copy link
Contributor

rcorre commented Mar 2, 2022

By directly interfacing with the script code

Is this a script attached to the AnimationTree? Or something you specify in a path? Or the parent node?

@David-Ochoa
Copy link

You need to attach a script to the Animation Tree and export some variables, in my case the variables are IsArmed and Is Attacking

@WindyDarian
Copy link
Contributor

Being able to have expression in condition helps a lot! I think this makes state machine much more flexible.

I was directed to here because I have a similar pr/proposal at #59872 / godotengine/godot-proposals#4352 . Do you think if it may still be worth allowing multiple transitions with the same from and to nodes with condition expression in? Since i think allowing multiple transitions addresses the "at end" part of condition @David-Ochoa mentioned above.

@fire
Copy link
Member

fire commented Apr 11, 2022

There was a sentiment that not everyone agreed on the approach. If there is agreement, we can salvage it.

Does anyone know what was the disagreement?

@David-Ochoa
Copy link

There was a sentiment that not everyone agreed on the approach. If there is agreement, we can salvage it.

Does anyone know what was the disagreement?

From me it was more about mistaking the intended functionality, now it's clear to me. I don't know if somebody else has a disagreement.

@SaracenOne
Copy link
Member

For me at least, I don't think there was a disagreement with this approach, it always seemed fine to me, just needing some extra polish with some UI issues surrounding it. My main concern is that while this approach for state machine transition seems fine, I was hoping we could decide on a similar approach for blend tree parameters, but perhaps its not worth holding up the implementation of this feature

Copy link
Member

@SaracenOne SaracenOne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will be fine to merge once conflicts are resolved. I'm happy to take over this PR if it would help. I think the one UX issue I have with this though is the defintion of the expression base node, specifically that using anything other than the AnimationTree itself as the expression base feels for unintuitive and bug prone given you have to manually. Something that might help with that is adding an expression base on the AnimationTree node itself which can be used as default for nodes where no expression base is defined.

@SaracenOne
Copy link
Member

@reduz I've updated this branch to be rebase it onto master, but also add a few things which should address some of the issues I noticed with it, mainly UX stuff: fixing the selection of the expression base node from the AnimationTreeEditor, fixing edge stripping causing problems when typing spaces at the beginning or end of a new expression, and adding the ability to set an expression base node on the AnimationTree node itself for when one isn't explictly specified by the transition nodes.
https://github.com/V-Sekai/godot/tree/animtree-advance-expressions

@reduz
Copy link
Member Author

reduz commented Apr 20, 2022

@SaracenOne feel free if you want to take it over to do a PR and co-author me

@SaracenOne
Copy link
Member

Yeah, happy to take this over since I realise I was one of the people who initially advocated for it, but generally, what's the process involved in doing so?

@Riteo
Copy link
Contributor

Riteo commented Apr 21, 2022

@SaracenOne Correct me if I'm wrong, but I think you just make a new PR and call it a day.

@fire
Copy link
Member

fire commented May 19, 2022

Superseded by: #61196

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

Successfully merging this pull request may close these issues.

10 participants