SyncVar initial state not sent for scene objects?

I’m probably missing something but I’ve been banging my head against a wall all day on this. I have a scene object script with a singleton, a seed value is set on the singleton in my network manager script’s Start() method, the seed value, an int, is a SyncVar. In the script with the seed value I have:

    public override void OnStartClient()
    {
        base.OnStartClient();
        build();
    }

build() uses the SyncVar value as a seed to build a level. However the initial value of the SyncVar isn’t set on the client by the time OnClientStart() is called. I’ve tried running in host mode to ensure that the value has been written on the server side by that point and it has. If I update the SyncVar value in [Server] Update() then the changes come through, but I can’t access the initial value which is what I need.

This should work. The code below works for me, with the “bug” script on a scene object with a NetworkIdentity.

public class MoveNetManager : NetworkManager
{
    public bug b;

    // Use this for initialization
    void Start () {
        b.seed = 88;
    }
}

public class bug : NetworkBehaviour {
    [SyncVar]
    public int seed;

    public override void OnStartClient()
    {
        Debug.Log("seed = " + seed);
    }
}

That’s more or less what I’m doing yes. The only significant difference is my NetworkManager subclass is accessing “bug” (LevelManager in my case) via a singleton rather than a member variable. The game object for NetworkManager does have a network identity.

In attempting to ensure I had a setup identical to your test script I have noticed what may be the issue though. I’ve realised I’m only seeing this behaviour on a build, not in the editor. In the editor, acting as server (host-local or remote), the value is initialised correctly and synced, however in a build it’s not and I’m getting the following exception:

NullReferenceException: Object reference not set to an instance of an object
at UnityEngine.Networking.NetworkBehaviour.SetSyncVar[Int32] (Int32 value, System.Int32& fieldValue, UInt32 dirtyBit) [0x00000] in C:\buildslave\unity\build\Extensions\Networking\Runtime\NetworkBehaviour.cs:457

at LevelManager.set_Networkseed (Int32 value) [0x00000] in :0

at VelocitronNetManager.Start () [0x00013] in F:\ACTIVE_Tolan_User_Folders_Moved\Documents\Velocitron\Assets\scripts\VelocitronNetManager.cs:13
(Filename: C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkBehaviour.cs Line: 457)

For reference, VelocitronNetManager.cs:13 is:

LevelManager.singleton.seed = seed;

So for some reason the Awake() on LevelManager, which creates the singleton, hasn’t been called by the time that VelocitronNetworkManager::Start() is called. Probably because LevelManager has a network identity so is disabled until connection. What I don’t understand though is why Awake() is called on it in the editor but not in a build, or how to work around it.

(Thanks by the way :slight_smile:

I ended up having to manually activate the LevelManager’s game object, set the seed then deactivate it again. If it’s not deactivated again then all hell breaks loose when joining a server.

public class VelocitronNetManager : NetworkManager
{

    public GameObject levelManagerGO;

    void Start()
    {
        System.Random rand = new System.Random();
        int seed = rand.Next(0, 10000);
        levelManagerGO.SetActive(true);
        LevelManager.singleton.seed = seed;
        levelManagerGO.SetActive(false);

This seems like a hack though. Having in-scene game objects with NetworkIdentities be disabled automatically until join has been really problematic for me.

Same here. Have to make sure anything that should run before a network connection does not have a network identity. But yeah, been a bit of refactoring for me too…

Having a NetworkIdentity on the NetworkManager is a "bad idea"™. Having the thing managing the network be managed by the network causes all kinds of problems. If you want a different manager, make it a different object from the NetworkManager.

Maybe that should even be forbidden by the components themselves…

1 Like

Ah I might not have been clear, the network identity is on the level manager not the network manager.

Also the Network manager has virtual functions that are called at better times than the normal Start() function…

        public virtual void OnStartHost()
        {
        }

        public virtual void OnStartServer()
        {
        }

        public virtual void OnStartClient(NetworkClient client)
        {
        }

        public virtual void OnStopServer()
        {
        }

        public virtual void OnStopClient()
        {
        }

        public virtual void OnStopHost()
        {
        }