simple setup issues... ClientRpc problems

I’m having trouble starting a turn-based game.

I’d like to create some object that only exists on the server and keeps track of game state, e.g. whose turn it is. I want each client to be able to send messages to this object, and for it to be able to send messages to all clients.

Sending Commands from the Players works, but sending ClientRpcs to all clients is a big source of confusion for me. I’m able to successfully send them when I call them from a Command in the Player script, but I can’t figure out how to send them from an object that exists only on the server.

Simply having a ServerGameController script on a gameobject in the scene and checking ServerOnly on its NetworkIdentity doesn’t seem to be enough - I believe because scripts must have been “spawned” to be able to send ClientRpcs.

So now I’m trying to figure out at what point (and from which other script) would be best to spawn my serverside game-state controller object, and everything already feels very messy and like I’m overcomplicating things.

If anyone knows a simple way to accomplish what I’m trying to do (have one server-side script that can receive Commands from both client Player scripts, and send ClientRpcs to both client Player scripts), or a better way to handle things if I’m going about it all wrong, help would be appreciated.

Why not spawn an object on both the server and client (using network instantiating) but only allow the server to run the game code?

As far as I understand it, when 2 players are connected and one is the host, there’s 2 clients and 1 server in the mix. If I spawn an object to control game state, won’t a copy exist on the server and on each of the clients?

I guess I’m too hung up on having the canonical game state ONLY existing on the server (and the server just telling each client when it’s their turn, etc)… but maybe having the game state be synced to all clients as well is a better approach. I think that’s what you’re suggesting, at least.

As an (untested) example, if you’ve spawned an object with the following script, the code that can set the player turn will only run on the server:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class GameController : NetworkBehaviour
{
    int thisPlayer = 2;

    [SyncVar]
    int playerTurn = 1;

    void Update ()
    {
        if(isLocalPlayer && Time.time > 15f)
        {
            //only executed on local player client, executed (every frame; oops) after 15 seconds
            CmdTellServerIveHadMyTurn();
        }
    }

    [Command]
    void CmdTellServerIveHadMyTurn()
    {
        //only executed on server
        playerTurn++;
        RpcNotifyClients(playerTurn);
    }

    [ClientRpc]
    void RpcNotifyClients(int turn)
    {
        if(thisPlayer == turn)
        {
            //my turn!
        }
        else
        {
            //not my turn!
        }
    }
}

Does that help? :slight_smile:

Thanks a lot man! I’m testing it out right now and it does feel quite nice and simple.
Couple more questions though if you don’t mind:

Right now I’m just treating this GameController object as my player prefab on the NetworkManager. Would you recommend spawning it from somewhere else, and where if so? Should I be subclassing NetworkManager and spawning some stuff there when the server is set up?

And I’m unsure about the best way to assign player 1 the id=1, and player 2 id=2 without doing something hacky.

I’m very much a beginner too, but yeah, you could look into subclassing NetworkManager to replace the virtual functions you need, giving it your own implementation. Here’s what you can override.