derkork / godot-statecharts

A state charts extension for Godot 4
MIT License
761 stars 39 forks source link

Provide an example of sharing behaviours between multiple entities. #132

Closed nickswebsite closed 2 weeks ago

nickswebsite commented 2 months ago

I suppose this is really more of a question than a feature request, but it might be good to see an example of some basic behaviours being shared between multiple characters.

One of the things I like about the FSMs that allow you to assign a script to each state is that the behaviour defined in these scripts can be shared across multiple entities. I've been struggling to find a clean way to do this.

Take as a trivialized example: Moving a CharacterBody2D to another point in the screen. There are generally two 'atomic' states you would need here:

  1. Rotating to face where the character is traveling,
  2. Actually moving there. At this point you might want to transition to some sort of success state or move on to a different activity.

Implementing these behaviours for a single character with it's own state chart is fairly straight forward. But, sharing certain basic behaviours across multiple characters hasn't been.

As a more concrete example, say, take some of the MObs from the original Legend of Zelda. Say, the Octorok, Lynel, and Rope. They all share the same 'patrol' pattern, but have different attack. Octoroks may shoot a rock, Lynel's may double fire a sword, and Ropes charge at Link. While this is certainly a relatively simple case that can be solved with some feature toggles, for games with a richer experience, this could become unwieldy.

How would you architect these 'prefabs' to share the same 'patrol' behaviour while allowing different attack patterns or other behaviours? Conversely, how could the attack patterns be shared while varying the patrol behaviour?

derkork commented 1 month ago

There are certainly a lot of ways in which this can be done. A relatively straigh-forward variant would be to have multiple smaller compound states handling the facets of the behaviour. E.g. there could be a scene with compound state modeling the patrol behaviour and another scene with a compound state modelling the attack behaviour. For each of these states there could be a script which implements the necessary callbacks from these states:

image

E.g. the scene for the patrol behaviour could look like this:

image

Now when you want to build a mob and combine behaviours, you can drag the prepared scenes into the state chart and wire them up as needed.

image

It will probably make sense to have a generic mob script at the root of the mob scene which will look for behaviour scripts (e.g. one could use a group to find them) and initialize them, so the behaviour scripts get access to the mob itself and can also move it and get access to the state chart.