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