Comparison

This page is part of the Game Manager example.

This page tries to explain the advantages and disadvantages of the two different approaches, but you should keep in mind that this example used an intentionally simple scenario which may somewhat bias your impressions.

Enum FSM
One large script, but less total code. Several small scripts, but more total code (mostly due to the additional Boilerplate Code required to define each state as a separate class).
Easy to use for simple tasks like this example, but doesn't scale well to more complex situations. Requires more initial effort to set up, but is much easier to maintain and expand in more complex scenarios.
Fields need longer names like _IntroductionOrbitSpeed to make their purpose clear (both in code and in the Inspector). Fields can have shorter names like _OrbitSpeed because they are only declared in the class where they are actually relevant (IntroductionState in that case).
The [Header] attribute can be used to group serialized fields into headings in the Inspector, but that doesn't help in code. Fields are automatically grouped in the Inspector because they are already in the classes they are relevant to.

Debugging

Fixing bugs in a system as you write it is generally fairly straightforward, but when problems inevitably occur later on after you have worked on many other things or in other people's code the process is often much harder. So try to consider the following potential problems as if you hadn't just gone through the implementation of the entire system in detail:

Problem Enum FSM
The internal state seems to have changed without applying the correct changes. Make sure the CurrentState property is the only place in the whole script where you set the _CurrentState field so that it always calls OnEnterState properly. That would never happen because the StateMachine doesn't let you set its CurrentState without it calling the appropriate OnExitState and OnEnterState methods.
The camera is orbiting faster than expected in the Introduction state. Make sure you only have one GameManagerEnum component in the scene. We already made the GameManagerFSM a Singleton so it would log an error if there were two of them in the scene.
There is a typo in the text displayed during the Ready state. Go to the OnEnterState method and look for the Ready case in its switch, then modify the line where the text is set. Go to the ReadyState script and modify its DisplayText property.
There is a typo in the text displayed during the Action state. Go to the OnEnterState method and realise that the Action state doesn't set it there so look around more and find the Action case in the Update method then modify the line where the text is set. Go to the ActionState script and modify its DisplayText property.

Expansion

Similarly, you will frequently need to make changes to your systems throughout development as you complete tasks and requirements change, so the difficulty for making modifications and adding new features is another important aspect to consider:

Task Enum FSM
Add a FixedUpdate method for some states to use.
  1. Add a FixedUpdate method in GameManagerEnum.
  2. Add the usual switch statement to do different things based on the current state.
  1. Add a virtual FixedUpdate method in the base GameManagerFSM.State class.
  2. Add a FixedUpdate method in GameManagerFSM which calls _StateMachine.CurrentState.FixedUpdate();.
That would be even easier in the FSM system if the base State inherited from StateBehaviour because we could just put a regular FixedUpdate method in the state that needs it without modifying anything else.
Add a Game Over state if the player takes too many swings.
  1. Add a GameOver value to the GameManagerEnum.State enum.
  2. Add any new fields is requires to the GameManagerEnum script.
  3. Add a case State.GameOver to the switch in OnStateEnter.
  4. Add a case State.GameOver to the switch in Update.
  5. Edit the FadeOut case in Update to choose between GameOver or FadeIn as the next state.
  1. Create a GameOverState script. All the fields and methods for the new state go in that script.
  2. Edit the FadeState script to check if it needs to enter the GameOverState when the fade out ends.
Find out why the Game Manager needs a reference to the _Ball.
  1. Find all references to the _Ball field.
  2. Go through them and see that they are all in the Action case in the Update method.
  1. It's a private field in the ActionState class and you can see everywhere it's used on the same screen.