How to change turns on button click using HLAPI?
So I've been stuck on this issue for a few days now and haven't been able to make this work. What I'm trying to do is make a turn-based game using the Unity HLAPI, and I'm trying to wrap my mind around the concepts of Commands, ClientRpc's, and all that stuff.
In order to help myself understand how simple client-server calls work, I have two objects in my scene: a Text box, and a Button. When one user presses the button, it should send a call to the server to tell it to change turns, and the Text box should reflect whose turn it is on each client. The caveat is that I don't want the ChangeTurn function to be called by anyone but the person whose turn it is, and that's where I'm hitting some roadbumps. I've tried all sorts of checks to make sure the presser of the button is the client/player whose turn it is by using isLocalPlayer, but it only seems to register the local player as whichever client is also hosting the server.
I'm using a singleton class to keep track of the state of the game, and I wonder if the error comes because there's only a single instance of the class, and so there can only be one localPlayer variable inside it...? ( localPlayer is a self-defined variable) Here's the relevant code from my Player and GameManager classes.
Player:
public override void OnStartLocalPlayer() {
GameManager.instance.localPlayer = this;
}
public int getID() { return playerID; }
public void setID(int id) { playerID = id; }
GameManager:
public static GameManager instance;
public List<Player> players = new List<Player>();
public Player localPlayer;
public Deck deck;
public GameTurnState currentState;
public int numPlayers = 0;
public Text messageBox;
public Button testButton;
[SyncVar(hook = "DisplayWhoTurn")]
public int currentPlayerTurn = 0;
// Initialize Singleton
void Awake () {
if(!instance) {
instance = this;
DontDestroyOnLoad(gameObject);
}
else Destroy(gameObject);
}
public override void OnStartClient() {
// Debug.Log("**** OnStartClient GameManager");
testButton.onClick.AddListener(RequestChangeTurn);
}
public void RequestChangeTurn() {
if (localPlayer.getID() != GameManager.instance.currentPlayerTurn) {
GameManager.instance.SetMessage("It's not your turn! It's " +
GameManager.instance.players[GameManager.instance.currentPlayerTurn].Name +
"'s turn!");
}
else {
CmdChangeTurn();
}
}
[Command]
public void CmdChangeTurn() {
ChangeTurn();
}
[Server]
public void ChangeTurn() {
int turn = currentPlayerTurn;
currentPlayerTurn = (turn + 1) % numPlayers;
}
public void DisplayWhoTurn(int currentPlayerTurn) {
// messageBox.text = "It's " + currentPlayerTurn + "'s turn!";
}
public void AddPlayer(Player player) {
players.Add(player);
numPlayers++;
}
public void RemovePlayer(Player player) {
players.Remove(player);
numPlayers--;
}
[Client]
public void SetMessage(string msg) {
messageBox.text = msg;
}
Then I also have a NetworkManager class that boots everything up on starting.
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) {
for (int slot = 0; slot < MAX_PLAYERS; ++slot) {
if (players[slot] == null) {
GameObject playerObj = GameObject.Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
Player player = playerObj.GetComponent<Player>();
player.Name = slot.ToString() + "-a";
player.setID(slot);
players[slot] = player;
GameManager.instance.AddPlayer(player);
Debug.Log("**** Adding new player with id: " + slot);
NetworkServer.AddPlayerForConnection(conn, playerObj, playerControllerId);
return;
}
}
conn.Disconnect();
}
If anybody can see what I'm doing wrong or assuming incorrectly, I'd be super appreciative to hear your words of wisdom! Thanks in advance.