Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

NetworkVariable initialization

Discussion in 'Netcode for GameObjects' started by Gadnuk, Jul 14, 2023.

  1. Gadnuk

    Gadnuk

    Joined:
    Jun 30, 2015
    Posts:
    3
    I cant seem to get this right and the docs dont really have great examples of how to spawn network objects dynamically.

    I've extracted the relevant pieces, though this is more or less what I have
    Code (CSharp):
    1.  
    2. namespace Test
    3. {
    4.  
    5.     public class TestNetworkBehavior : NetworkBehaviour
    6.     {
    7.  
    8.         public NetworkVariable<int> networkedProps = new();
    9.  
    10.         public static TestNetworkBehavior Spawn(int whatever)
    11.         {
    12.            var prefab = Resources.Load(resource);
    13.            var networkObject = prefab.GetComponent<NetworkObject>();
    14.  
    15.            if (networkObject)
    16.            {
    17.              // Spawning a networked object can only be done by Server
    18.              if (!Network.IsAuthority)
    19.              {
    20.                 return null;
    21.              }
    22.  
    23.              var instance = Object.Instantiate(prefab);
    24.              var controller = instance.GetComponent<TestNetworkBehavior>();
    25.              // never reflected on client
    26.              controller.networkedProps.Value = whatever;
    27.  
    28.              // Spawn the NetworkObject and re-parent
    29.              networkObject.Spawn();
    30.              // ...
    31.  
    32.              return controller;
    33.  
    34.            else {
    35.                ...
    36.            }
    37.         }
    38.    
    39.         // This is only being called on the Client
    40.         public override void OnNetworkSpawn()
    41.         {
    42.             base.OnNetworkSpawn();
    43.             Debug.Log("network spawn");
    44.             Debug.Log(this.networkedProps.Value);  // >>> 0
    45.         }
    46.    
    47.         public void Start()
    48.         {
    49.             Debug.Log("start");
    50.             if (Network.IsAuthority)
    51.             {
    52.                 // never reflected on client
    53.                 networkedProps.Value = 222;
    54.             }
    55.        
    56.             // Client logs 0. Server logs 222
    57.             Debug.Log(networkedProps.Value);
    58.         }
    59.     }
    60. }

    The server logs

    NetworkVariable is written to, but doesn't know its NetworkBehaviour yet. Are you modifying a NetworkVariable before the NetworkObject is spawned?

    This happens when the server tries to assign networkProps.value. It doesn't seem to make sense because Start should be called after OnNetworkSpawn so the network should be synced at that point. I could try to assign it on the server in OnNetworkSpawn but...

    I noticed that OnNetworkSpawn is only ever called on the Client, its never used on the server. This doesnt seem like the expected behavior as the docs make it look like this method should be invoked on the server as well.

    Can also reference a related post: https://forum.unity.com/threads/how...ue-on-a-client-during-onnetworkspawn.1431835/
    It seems like on their OnNetworkSpawn the Client gets the updated value - in my case the client never updates. The server does spawn my object and assigns the NetworkObject and Id etc so I dont think its a config issue

    Any help is greatly appreciated - thank you!
     
    Last edited: Jul 14, 2023
  2. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    218
    Start() is called on the beggining, when this object is instantiated or spawned. Spawning the network object takes time, so when you instantiate it on the server the start is called before it is spawned and it changes the network variable value before it is spawned. On the client, when the start method is called it still haven't spawned so it logs 0.

    The OnNetworkSpawn should be called on both the server and the client. It is weird you don't get it called on the server. Additionally, if you change on the server the value of networkedProps before spawn it should still sync to the client after spwan. Maybe try on OnNetworkSpawn to add a callback to whenever the network variable changes value and check if it's called. Maybe the client gets the new value only later.

    You can try adding
    controller.networkedProps = new NetworkVariable<int>();

    before spawning the object and maybe it will help.

    When do you call your spawn method?
     
  3. lavagoatGG

    lavagoatGG

    Joined:
    Apr 16, 2022
    Posts:
    218
    Try
    var networkObject = instance .GetComponent<NetworkObject>();

    And then it will spawn the modified instance and not the prefab.
     
    Gadnuk likes this.
  4. Gadnuk

    Gadnuk

    Joined:
    Jun 30, 2015
    Posts:
    3
    Thanks for the quick response!

    Oh wow i bet that's it - its probably using the prefab NetworkObject instead of the instantiated instance. It's pretty late here but I'll give this a shot first thing in the AM and accept the answer. thank you so much!!