I’m trying to set up a very simple game of something like checkers. I’ve been trying for days to get this to work and I am totally befuddled by the Unity network model. None of the examples out there are complete and the documentation isn’t helping me understand the subtleties of clients vs servers vs hosts.
Here’s what I want to do: The host receives “move requests” from each player, and is responsible for broadcasting to all players moves that actually change the game state. I imagine it functioning like this.
- A player chooses to host a game. (the “host”)
- Another player chooses to join the game. (the “client”)
- A player (host or client) taps on their screen attempting to play a piece. The tap is converted to a potential move on the board, and message like this is sent to the host: “Player 1: Place at 3,5”
- The host decides if it is a legal move. If it is, the host broadcasts the legal move to everyone (the host and the client)
- Each instance of the game receives the message from the host and places the piece on the board and shows appropriate animations, etc.
I’m not even sure of the right approach to do this, but since I want to take advantage of functionality in the NetworkManager and NetworkHUD, I decided to try using the technique most frequently demoed, which involves arcade game networking. Not ideal, but it should work, right?
I set up a simple 2D game with a canvas and a panel and an object for the network manager/HUD with custom code. What I find is that I am unable to get communications to flow from the client to the host. Here is my code:
public static class MessageType { public const int TEST = 1000; }
public class TestMessage : MessageBase { public string text; }
public class MyNetworkManager : NetworkManager {
public override void OnStartClient(NetworkClient client)
{
base.OnStartClient(client);
client.RegisterHandler(MessageType.TEST, OnClientHandleTestMessage);
}
public override void OnStartServer()
{
base.OnStartServer();
NetworkServer.RegisterHandler(MessageType.TEST, OnServerHandleTestMessage);
}
private void OnClientHandleTestMessage(NetworkMessage netMsg)
{
var message = netMsg.ReadMessage();
Debug.Log("CLIENT Got a test message: " + message.text);
}
private void OnServerHandleTestMessage(NetworkMessage netMsg)
{
var message = netMsg.ReadMessage();
Debug.Log("SERVER Got a test message: " + message.text);
}
}
public class GamePanel : MonoBehaviour {
void Update () {
if (Input.GetKeyUp(KeyCode.Mouse0))
{
Debug.Log(“PanelClick”);
NetworkServer.SendToAll(MessageType.TEST, new TestMessage() { text = "panel click " });
}
}
}
public class NetworkPlayer : NetworkBehaviour {
void Update () {
var idText = (isServer ? “P1” : “P2”) + “[” + this.netId + “]”;
if (Input.GetKeyUp(KeyCode.Mouse0))
{
Debug.Log("PlayerClick: " + idText);
NetworkServer.SendToAll(MessageType.TEST, new TestMessage() { text = "Click: " + idText });
}
}
}
The output is wildly different depending on if I am running as the client or the host. The output of the host has not messages from the client. The output of the client also has no messages from the client, but it does see message from the host. Only the client message handlers are tripped. The server message handlers are silent, which I did not expect at all.
---- Debug output on the host
[Click on “LAN Host” in the host]
PanelClick
CLIENT Got a test message: panel click
[Click on Panel in the host]
PanelClick
PlayerClick: P1[1]
CLIENT Got a test message: panel click
CLIENT got a test message: Click: P1[1]
[Click on “Client” in the client]
(no output, but it reports being connected and server shows additional player object)
[Click on the panel in the client]
(no output)
[Click on Panel in the host]
PanelClick
PlayerClick: P1[1]
PlayerClick: P1[2]
CLIENT Got a test message: panel click
CLIENT got a test message: Click: P1[1]
CLIENT got a test message: Click: P1[2]
---- Debug output on the client
[Click on “LAN Host” in host]
(no output of course, but the app shows it is hosting)
[Click on “Client” in client]
PanelClick
[Click on panel in the client]
PanelClick
PlayerClick: P2[1]
PlayerClick: P2[2]
[Click on panel in the host]
CLIENT Got a test message: panel click
CLIENT got a test message: Click: P1[1]
CLIENT got a test message: Click: P1[2]