Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Networking SyncVar initial state not sent for scene objects?

Discussion in '5.1 Beta' started by sligit, May 31, 2015.

  1. sligit

    sligit

    Joined:
    May 25, 2015
    Posts:
    12
    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:
    Code (CSharp):
    1.     public override void OnStartClient()
    2.     {
    3.         base.OnStartClient();
    4.         build();
    5.     }
    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.
     
  2. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    This should work. The code below works for me, with the "bug" script on a scene object with a NetworkIdentity.

    Code (CSharp):
    1. public class MoveNetManager : NetworkManager
    2. {
    3.     public bug b;
    4.  
    5.     // Use this for initialization
    6.     void Start () {
    7.         b.seed = 88;
    8.     }
    9. }
    10.  
    11. public class bug : NetworkBehaviour {
    12.     [SyncVar]
    13.     public int seed;
    14.  
    15.     public override void OnStartClient()
    16.     {
    17.         Debug.Log("seed = " + seed);
    18.     }
    19. }
    20.  
     
  3. sligit

    sligit

    Joined:
    May 25, 2015
    Posts:
    12
    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 <filename unknown>: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.
     
  4. sligit

    sligit

    Joined:
    May 25, 2015
    Posts:
    12
    (Thanks by the way :)
     
  5. sligit

    sligit

    Joined:
    May 25, 2015
    Posts:
    12
    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.

    Code (CSharp):
    1. public class VelocitronNetManager : NetworkManager
    2. {
    3.  
    4.     public GameObject levelManagerGO;
    5.  
    6.     void Start()
    7.     {
    8.         System.Random rand = new System.Random();
    9.         int seed = rand.Next(0, 10000);
    10.         levelManagerGO.SetActive(true);
    11.         LevelManager.singleton.seed = seed;
    12.         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.
     
  6. Shinyclef

    Shinyclef

    Joined:
    Nov 20, 2013
    Posts:
    505
    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...
     
  7. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    Having a NetworkIdentity on the NetworkManager is a "bad idea"(tm). 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...
     
    christophermrau likes this.
  8. sligit

    sligit

    Joined:
    May 25, 2015
    Posts:
    12
    Ah I might not have been clear, the network identity is on the level manager not the network manager.
     
  9. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    Also the Network manager has virtual functions that are called at better times than the normal Start() function..

    Code (CSharp):
    1.         public virtual void OnStartHost()
    2.         {
    3.         }
    4.  
    5.         public virtual void OnStartServer()
    6.         {
    7.         }
    8.  
    9.         public virtual void OnStartClient(NetworkClient client)
    10.         {
    11.         }
    12.  
    13.         public virtual void OnStopServer()
    14.         {
    15.         }
    16.  
    17.         public virtual void OnStopClient()
    18.         {
    19.         }
    20.  
    21.         public virtual void OnStopHost()
    22.         {
    23.         }