M
M
Michaellux2019-03-12 10:53:31
Unity
Michaellux, 2019-03-12 10:53:31

How to properly implement the "State" pattern in Unity?

I want to implement the "State" template.
To this end, I created an abstract class "GameState" and an empty Gameobject in the Hierarchy view with the same name.
5c87638b1f52a157785019.png
But it became clear that it is not possible to attach a script with an abstract class.
5c8763dedf4df614782111.png
Then I attached a GameObject with the class "GameManager" to the "GameState" script:
5c8763f767ab5967943408.png
GameState.cs:

public abstract class GameState : MonoBehaviour
 {
     [SerializeField]
     protected static GameObject gameManagerObject;
     protected GameManager gameManager = gameManagerObject.GetComponent<GameManager>();
 
     internal virtual void HandleButton(GameManager gameManager, PressedButton button)
     {
         ChangeState(gameManager, button);
     }
 
     protected abstract void ChangeState(GameManager gameManager, PressedButton button);
 
 }
 
 internal class StartState : GameState
 {
     internal StartState()
     {
         Debug.Log("Launch game");
     }
 
     protected override void ChangeState(GameManager gameManager, PressedButton button)
     {
         gameManager.State = new WorkState();
     }
 }
 
 internal class WorkState : GameState
 {
     internal WorkState()
     {
         gameManager.DoSomething(false);
     }
 
     protected override void ChangeState(GameManager gameManager, PressedButton button)
     {
         gameManager.State = new PauseState();
     }
 }
 
 internal class PauseState : GameState
 {
     internal PauseState()
     {
         Debug.Log("Pause");
         gameManager.DoSomething(true);
     }
     protected override void ChangeState(GameManager gameManager, PressedButton button)
     {
         gameManager.State = new WorkState();
     }
 }

GameManager.cs:
public class GameManager : MonoBehaviour
 {
     internal GameState State { get; set; }
 
     ...
 
     void Start()
     {
         ...
         State = new StartState();
     }
 
     public void FindOut(PressedButton button)
     {
         State.HandleButton(this, button);
     }
     ...
 }

But when I run it, I get an error:
5c87647a06fb9401775359.png
This is because I'm using the "new" keyword: How can I solve this problem? Is it even possible to implement the "State" pattern in this way? How to do it correctly in Unity?
State = new StartState();

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Denis Gaydak, 2019-03-12
@Michaellux

why do you need GameState : MonoBehaviour ?? why do you need it on the object in the scene?
the state is an abstract thing))
GameManager : MonoBehaviour is the norm. Let the manager live in the scene and initialize it.
but about the error - you can not create MonoBehaviour through NEW.
only through adding or searching for a component.
or

state = someRef.gameobject.GetComponent<GameState>()

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question