Blocking State Machine for turn-based system
Hi,
My goal is to create a Go game on Unity, but I'm having trouble in designing the turn-based system. I followed this tutorial to implement a simple state machine for turn-based system, but it seems that I can't block the switch statement to wait for a player finishing his turn.
The thing is I'd like to implement player vs. player and player vs. ai as simple as possible. I created two gameObjects : player and opponent, so that I can AddComponent the proper script I need (player or AI) in the opponent's gameobject
I know i'm not supposed to block an Update() function, and coroutines aren't the solution I need. I really need to split my turn-based system step by step :
1 - Player turn, he has to place a pawn on the board
2 - Opponent turn, if this is a player, simply places a pawn on the board, else if this is an AI, runs an algorithm then places a pawn on the board.
My second problem is that, to represent the board, I have a grid of tiles which have an Highlighter script in it to "highlight" the pawn placement. The color is dependant from the turn (player or opponent), and I'm afraid that if I block in the turn-based system, it'll block the Highlighter script (which contains Unity functions like OnMouseOver etc...)
Could anyone help me solving this ? :)
Have a good day !
Answer by Statement · Nov 07, 2015 at 08:02 PM
I don't know if you need to make a state machine. To me it just sounds like you tell a player script that it is their turn and when the player is done, they tell the game they ended the turn.
 public Material highlight;
 public Player player1, player2;
 Player current;
 
 void Start()
 {
     current = player1;
     current.BeginTurn(this); // tell the player its their turn
 }
 
 void Update()
 {
     if (highlight && current)
         highlight.color = current.color; // set material color to players color
 }
 
 public void EndTurn() // called by the current player
 {
     SwapPlayer();
     current.BeginTurn(this); // tell the next player to have a go at it
 }
 
 void SwapPlayer()
 {
     current = current == player1 ? player2 : player1;
 }
And to make it work with a human, AI or whatever you can think of, subclass player to the concrete type.
 public class HumanPlayer : Player
 {
     void Update() {
          if (!hasTurn)
              return;
          // if you need updates etc
     }
 }
 
 public class AIPlayer : Player
 {
      public Board board;
      public override void BeginTurn(Game game)
      {
           AIEngine.PerformBestMove(board);
           game.EndTurn();
      }
 }
Hi @Statement and thanks for your reply !
Here is my Highlighter script which "spawns" a pawn when hovering a tile of the board :
 public class            Highlighter : $$anonymous$$onoBehaviour {
 
     private GameObject    instantiated = null;
 
     public GameObject    pawn;
     
     void                On$$anonymous$$ouseOver () {
         Color            newColor;
         Color            pawnColor;
 
         if (instantiated == null) {
             instantiated = (GameObject) Instantiate (pawn, gameObject.transform.position, Quaternion.identity);
             instantiated.transform.parent = gameObject.transform;
             instantiated.name = "Pawn (Ghost)";
             pawnColor = Game$$anonymous$$anager.instance.getPawnColor();
             newColor = new Color(pawnColor.r, pawnColor.g, pawnColor.b);
             newColor.a = Game$$anonymous$$anager.instance.getPawnOpacity();
             instantiated.GetComponent<Renderer>().material.color = newColor;
         }
     }
 
     void                On$$anonymous$$ouseDown () {
         Game$$anonymous$$anager.instance.nextTurn ();
         this.On$$anonymous$$ouseExit ();
     }
 
     void                On$$anonymous$$ouseExit () {
         if (instantiated != null)
             Destroy (instantiated);
     }
 }
This script is attached to every "Tile" gameobject, it needs to know which color is the tile by asking for the current turn (player or opponent). When I try to make a "blocking" state machine in the Update() function of my TurnBasedSystem, the game seems not to launch at start and Unity crashes :
 public class                 TurnBasedSystem : $$anonymous$$onoBehaviour {
 
     private $$anonymous$$onoBehaviour    playerScript;
     private $$anonymous$$onoBehaviour    opponentScript;
 
     public GameObject        player;
     public GameObject        opponent;
 
     // Use this for initialization
     void                     Start () {
         playerScript = player.GetComponent<PlayerScript> ();
         if (Game$$anonymous$$anager.instance.getOpponent () == 0)
             opponent.gameObject.AddComponent<PlayerScript> ();
         else
             opponent.gameObject.AddComponent <AIScript> ();
         opponentScript = opponent.gameObject.GetComponent<$$anonymous$$onoBehaviour> ();
}
     // Update is called once per frame
     void                     Update () {
         while (Game$$anonymous$$anager.instance.getCurrentState() != GameState.END) {
             Debug.Log("Runnin' !");
         }
     }
 }
$$anonymous$$y first thoughts were that I need to put the turn-based system in a Coroutine but it seems that he doesn't work aswell. How can I manage to solve this ?
I don't understand what you want to put in the Coroutine? What kind of stuff goes in there?
      while (Game$$anonymous$$anager.instance.getCurrentState() != GameState.END) {
          Debug.Log("Runnin' !");
      }
Well, yeah, that will lock up the game and generate a mighty log...
I'd just send messages to begin the turn. Whenever the player want to end the turn, I tell the other guy to begin the turn, and so on.
If you really want to make use of Coroutines, just do it in Start.
 IEnumerator Start()
 {
     Initialize(); // Whatever, your code you had before.
     while (Game$$anonymous$$anager.instance.getCurrentState() != GameState.END)
     {
         yield return StartCoroutine(Step1());
         yield return StartCoroutine(Step2());
     }
 }
 
 IEnumerator Step1()
 {
     // But what do you do here?
     print("Step 1");
     yield return new WaitForSeconds(1);
 }
 
 IEnumerator Step2()
 {
     // And here?
     print("Step 2");
     yield return new WaitForSeconds(1);
 }
Answer by MajorSquirrel · Nov 08, 2015 at 02:15 PM
Done. Thanks to @Statement who guided me to a simple process. :)
I have :
- a GamePreferences gameobject with static instance which contains preferences (pawn colors, ai or player) stored trough scenes (instead of Prefabs) 
- a TurnBasedSystem gameobject with static instance which stores both entities (player and opponent) 
- Player & Opponent gameobjects which contains the StartTurn() method (so they can interact with EndTurn() method from static TurnBasedSystem when they finished their turn) 
- and a Highlighter script attached to each tile of my board to make a "ghost pawn" while hovering over a tile 
Highlighter consumes TurnBasedSystem to know which player is playin to get the matching pawn color.
do you $$anonymous$$d if ill ask how exactly you created the Grid system? i'm struglling at it very much. i'm working on a Heros of $$anonymous$$ight & $$anonymous$$agic style of a game but I cant figure a way to create a good and working tile system that will highlight grids when I Hover and select them
Your answer
 
 
             Follow this Question
Related Questions
How to make turnbase multiplayer game using photon ? 2 Answers
How to make a Inventory Hotbar 0 Answers
 koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                