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 a generalized StateMachine node #9517

Open
emmetoneillpdx opened this issue Apr 14, 2024 · 1 comment
Open

Add a generalized StateMachine node #9517

emmetoneillpdx opened this issue Apr 14, 2024 · 1 comment

Comments

@emmetoneillpdx
Copy link

Describe the project you are working on

My development partner and I have a couple of different games brewing including an arcade-style game with a variety of character interactions, a multiplayer puzzle game, a top-down action game, etc.

Describe the problem or limitation you are having in your project

Just about every game I can think of, including the ones I'm working on, relies heavily on finite state machine logic for everything from managing game states, character movement, animation, object interactions, puzzles, "ai" behavior, event scripting, and so on. The essence of a fighting game character, for example, is a complex state machine. As is the logic which controls the turns during a turn-based tactical RPG. State machines are everywhere.

Of course, all of this is possible in current versions of Godot using simple match statements and state enums, or by delegating behavior to state Nodes, as described here and here.

However, for such a common pattern in game design there is more than a little bit of boilerplate code needed to manage state Nodes, especially considering the existence of the AnimationTree Node--which is already an almost perfectly good finite state machine controller with a pretty nice visual editor!

On top of that, having many states appear as a simple list of Nodes in the SceneTree isn't a great way to visualize which state is currently active or how the states relate to each other.

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

As such, my proposal is to create a generalized StateMachine Node type, which represents a finite state machine (that may or may not be associated with animation) and could be used for a wide variety of different applications across just about any kind of game.

A StateMachine Node would manage a finite number of States and Transitions, and by attaching scripts to the StateMachine Node, as well as the individual States, we would create a very simple and standard way of making a Node that acts as a finite state machine with much less boilerplate code.

The StateMachine Node could potentially be used to deprecate, and eventually replace, the current AnimationTree Node as a more generalized, fundamental and flexible tool.

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

  • Adding a StateMachine Node to a scene would create a basic, logical Node that represents any finite state machine and appears to change behavior as it internally switches between active States.
  • Selecting the StateMachine Node and clicking a StateMachine tab at the bottom of the editor would open a GUI for managing its various internal State objects, attaching scripts, associating animations, signals, state groups, transitions, etc.
  • Because character states are often associated with animations (and because the StateMachine node should be just as easy to use as the AnimationTree) a StateMachine node should be able to be associated with an AnimationPlayer. This would allow you to use a StateMachine much in the same way that we currently use the AnimationTree, by creating new states from existing animations as well as using the current state of the node to control complex animation playback and blending.
  • Much like attaching GDScript to a Node, attaching a new GDScript to a State object would load up a template script with typical state-related functions like func enter, func exit, etc. From there, arbitrary data and functions could be added to each State as needed depending on the use case in question.
  • States would maintain their own built-in signals like signal entered and signal finished, which could be used by the StateMachine to transition to another state based on the configuration of the state graph, among other things. (States might emit signal finished when their associated animation is over OR in the case of non-animated/looping/logical states at any arbitrary point in time.)
  • Once a State emits signal finished it will follow one of its transitions (if it has any) in order to enter another State. A State with multiple out-bound transitions would select one transition to follow based on its configuration. (For example, to select one at random, to follow each branch as a sequence, to follow a branch conditionally, etc. Allowing for the creation of behavior trees.)
  • Each StateMachine node would also maintain their own list of State Groups which, like Scene Groups and Global Groups, could be activated and deactivated on each State object as needed. (For example, a character's StateMachine might have a State Group called "JumpCancelable" which could be used to easily determine which states can be jumped out of.)
  • Just like the current AnimationNodeStateMachine of the AnimationTree, StateMachine nodes could contain nested state machines.

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

At a basic level, this can be worked around using the "traditional" match-based or node-based methods of building state machines in Godot.

However, some of the aspects of this proposal are currently not possible at all (for example, State Groups, or creating "empty" States without existing animations inside a AnimationNodeStateMachine).

I also think creating a StateMachine node that's more loosely coupled with the animation systems creates a pipeline benefit, as it would allow teams with a dedicated designer (who may not be a programmer or animator) to quickly and easily define or tweak various StateMachines and State graphs, even before any code has been implemented or animations have been created. And by using the existing AnimationTree GUI, much of this work could be done visually, right in the Godot editor.

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

I think that StateMachines are just as fundamental to practically every game as other core node types, like CanvasItems, Node3Ds, etc., and I'm confident that a wide variety of games would be able to find multiple ways to use this node.

On top of that, in the context of controlling animation, Godot's AnimationTree is already a solid and functional finite state machine with a good editor. But while StateMachines are certainly an important part of game animation, their use goes far beyond animation alone, whether that's controlling the state of individual objects in a game world, managing the state of a puzzle or dungeon, or even managing the broad game states of an entire game.

Based on all of that, I feel that a generalized StateMachine node would represent a more fundamental and flexible tool than the current AnimationTree, while building on top of the things that make the current AnimationTree nice to work with.

@AThousandShips
Copy link
Member

See also:

I'd say this is something that's too general to be in core, any standard system for this would be too simple to cover everything, it's better as a plugin or add-on, and it can be implemented in scripting with GraphEdit and similar systems

@Calinou Calinou changed the title Include a generilzed StateMachine node. Add a generalized StateMachine node Apr 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants