I'm new to unity and I've been following and combining examples from tutorials to put together a simple boardgame-like demo using a 3d die from this tutorial: https://www.youtube.com/watch?v=LHQ4ynQhPLY and a boardgame tile setup using this tutorial: https://www.youtube.com/watch?v=d1oSQdydJsM along with a turn-based system from this tutorial: https://www.youtube.com/watch?v=W8ielU8iURI
While I have a fully working 3d die and I can get my pieces to move the appropriate number of spaces, I find myself having a difficult time incorporating the turn-based aspect.
My project file can be downloaded here: https://drive.google.com/drive/folders/1Odj3iqeYAaO3lnkzGOjwyxIdL0g00Xge?usp=sharing
For those not willing to download the project file, I will try to elaborate here:
I have six main scripts: Dice.cs, DiceSide.cs, ButtonHandler.cs, PlayerPiece.cs, Route.cs and GameControl.cs.
I excluded DiceSide.cs since this code isn't broken. It merely detects which side is on the ground so that I can detect that the opposite side is the die's value, which is stored in the diceValue variable in the code below.
I also excluded Route.cs since this also isn't broken. It defines the pathing route for the player pieces based on the position of the children objects of the "Board" game object.
Finally, I also excluded ButtonHandler.cs which is just a simple function that tells a button when it is clicked to roll the dice using the RollDice() function found in Dice.cs
Dice.cs (attached to the "Die" prefab):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Dice : MonoBehaviour
{
Rigidbody rb;
bool hasLanded;
bool thrown;
Vector3 initPosition;
public int diceValue;
public DiceSide[] diceSides;
public bool IsDoneRolling;
public int whosTurn = 1;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
initPosition = transform.position;
rb.useGravity = false;
}
// Update is called once per frame
void Update()
{
if (rb.IsSleeping() && !hasLanded && thrown)
{
hasLanded = true;
rb.useGravity = false;
rb.isKinematic = true;
SideValueCheck();
if (whosTurn == 1)
{
GameControl.MovePlayer(1);
}
else if (whosTurn == -1)
{
GameControl.MovePlayer(2);
}
whosTurn *= -1;
}
else if (rb.IsSleeping() && hasLanded && diceValue == 0)
{
RollAgain();
}
}
public void RollDice()
{
if (!thrown && !hasLanded)
{
IsDoneRolling = false;
thrown = true;
rb.useGravity = true;
rb.AddTorque(Random.Range(0,250), Random.Range(0,250), Random.Range(0,250));
}
else if (thrown && hasLanded)
{
Reset();
}
}
void Reset()
{
transform.position = initPosition;
thrown = false;
hasLanded = false;
rb.useGravity = false;
rb.isKinematic = false;
IsDoneRolling = true;
}
void RollAgain()
{
Reset();
IsDoneRolling = false;
thrown = true;
rb.useGravity = true;
rb.AddTorque(Random.Range(0,250), Random.Range(0,250), Random.Range(0,250));
}
void SideValueCheck()
{
diceValue = 0;
foreach (DiceSide side in diceSides)
{
if (side.OnGround())
{
diceValue = side.sideValue;
Debug.Log(diceValue + " has been rolled!");
}
}
}
}
PlayerPiece.cs (attached to each of the two player gameobject prefabs):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerPiece : MonoBehaviour
{
public Route currentRoute;
int routePosition;
public bool isMoving;
public bool moveAllowed;
public static int steps = 0;
// Update is called once per frame
void Update()
{
if (!isMoving)
{
StartCoroutine(Move());
moveAllowed = false;
}
}
IEnumerator Move()
{
if (isMoving)
{
yield break;
}
isMoving = true;
while (steps > 0)
{
Debug.Log("Route position: "+routePosition);
routePosition++;
routePosition %= currentRoute.childNodeList.Count;
Vector3 nextPos = currentRoute.childNodeList[routePosition].position;
while (MoveToNextNode(nextPos)) { yield return null; }
yield return new WaitForSeconds(0.1f);
steps--;
}
isMoving = false;
}
bool MoveToNextNode(Vector3 goal)
{
return goal != (transform.position = Vector3.MoveTowards(transform.position, goal, 8f * Time.deltaTime));
}
}
GameControl.cs (attached to an empty gameobject):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameControl : MonoBehaviour
{
private static GameObject player1, player2;
public static int diceSideThrown = 0;
// Start is called before the first frame update
void Start()
{
player1 = GameObject.Find("Player1-Piece");
player2 = GameObject.Find("Player2-Piece");
player1.GetComponent<PlayerPiece>().moveAllowed = false;
player2.GetComponent<PlayerPiece>().moveAllowed = false;
}
// Update is called once per frame
void Update()
{
if (player1.GetComponent<PlayerPiece>().moveAllowed)
{
//Move the player 1 piece... code in PlayerPiece.cs
}
if (player2.GetComponent<PlayerPiece>().moveAllowed)
{
//Move the player 2 piece... code in PlayerPiece.cs
}
}
public static void MovePlayer(int playerToMove)
{
switch (playerToMove)
{
case 1:
player1.GetComponent<PlayerPiece>().moveAllowed = true;
break;
case 2:
player2.GetComponent<PlayerPiece>().moveAllowed = true;
break;
}
}
}
So what should happen is that which I click the button, the RollDice() function in Dice.cs fires (working) which rolls the dice and generates the value of spaces the player has to move (working) and then only player 1 should move that number of spaces (not working, obviously because this part isn't connected in GameControl.cs however the movement code in PlayerPiece.cs is demonstrated to work in my non-turnbased testing). After Player 1 finishes moving, clicking the same button should roll the dice, repeating the steps except only player 2 should move the new number of spaces generated.
I know all the pieces are there, but I'm at a loss as to how to get them to fit together to work as intended.
Your help is greatly appreciated.