Scripting with Playmaker FSM and separating concerns

Hi. There isn’t a clear place to ask this questions so the scripting forum is my best guess. I am struggling with a good, scalable, sensible pattern for using Playmaker FSMs and scripts to build my game.

I’m currently prototyping. I’ll try to illustrate my example in a simplified and contrived way. Just bear with me. :slight_smile:

I have a prefab of a car. The car has an engine. There is a simple Canvas UI that has three buttons.

Button1: should toggle the engine on or off
Button2: shifts the car into forward gear
Button3: shifts the car into reverse gear

Some logics:
The engine should only run if the car is in one gear or another.
The engine, if running, should stop if there is no more fuel
The car can only be in one gear or the other (obvs)

So, what I am struggling with is where to put all this logic. Some things feel they should be in script(s). Some concerns feel like they should be in the FSM. I am not finding any clear examples of how to break something like this down and create a scalable pattern.

I liked the idea of using the FSM for control flow and the UI and then passing messages to scripts. This quickly gets a little clunky but maybe I haven’t found the right way yet. I’ve had some iterations worse than others.

I like the idea of passing events between FSMs but they can’t all be global. This car prefab will be in my seen in multiple instances. I can’t have a button click putting them all into forward gear!

I may, of course, be missing something.

Again, my ask is: what is a good way to approach what goes in FSMs internally and what can go in scripts and, in the case of the latter, how to integrate the two.

I think I’ve watched every Playmaker video on the youtubes and, I’ve gotten closer but it still feels messy.

Your engine is clearly an FSM, with the following states

1 - Running forward

  • Transition to stop if fuel empty or car turned off
  • Transition to running reverse if gear changed

2 - Running reverse

  • Transition to stop if fuel empty or car turned off
  • Transition to running forward if gear changed

3 - Stopped

  • Transition to running forward if car started and fuel is not empty and car is in forward gear
  • Transition to running reverse if car started and fuel is not empty and car is in reverse gear

The rest is slightly less clear. In code I would simply go ahead and define a bool for the current gear. You could set up an entire FSM for it, but it seems overkill for just two states. You could do the same for on/off and fuel full/empty if you like.

Great! Thank you. And how would you wire in the UI? Say, the button to shift into fwd gear?

Also, if the engine is running, is that an FSM variable referenced by the Engine script or vice versa?

Unfortunately I don’t have enough familiarity with how playmaker works to offer more specific advice.

Create an FSM. This is a perfect use case for PlayMaker. I added another state (Park) because you didn’t specify what happens if the player starts the engine. You could just as easily have it pop immediately into Drive.

State: Off

  • Action: Stop the engine

  • Custom Event: PowerButton transition to Park

State: Park

  • Custom Event: PowerButton transition to Off
  • Custom Event: ShiftForward transition to Drive
  • Custom Event: ShiftReverse transition to Reverse

State: Drive

  • Action: Start the engine (if necessary)

  • Action: Roll forward (every frame)

  • Action: Decrease fuel (every frame)

  • Action: Check fuel (every frame). If empty, transition to Off

  • Custom Event: PowerButton transition to Off

  • Custom Event: ShiftReverse transition to Reverse

State: Reverse

  • Action: Start the engine (if necessary)

  • Action: Roll backward (every frame)

  • Action: Decrease fuel (every frame)

  • Action: Check fuel (every frame). If empty, transition to Off

  • Custom Event: PowerButton transition to Off

  • Custom Event: ShiftForward transition to Drive

You didn’t specify if each car has its own UI (e.g., a world space UI located on the car). If so:

  • Configure button 1’s OnClick() to call the FSM’s SendEvent method. Set the string value to PowerButton.
  • Configure button 2’s OnClick() to call the FSM’s SendEvent method. Set the string value to ShiftForward.
  • Configure button 3’s OnClick() to call the FSM’s SendEvent method. Set the string value to ShiftReverse.
1 Like