SyncList not Initialized during Awake()

I am using SyncLists and I notice they throw errors when I use them during the Awake() method. This seems to be new to 5.2. Anybody else having this problem?

The flow I’d like to achieve is:
-Instantiate object on server
-Set SyncVar’s during server Awake()
-Spawn object on client. All SyncVar’s should be set by the spawn so correct values are there when OnStartClient() is called… this is why I’m trying to set SyncVar’s during Awake() and not Start()

using UnityEngine;
using System.Collections;
using UnityEngine.Networking; //needed for NetworkBehavior

public class TestSyncListAwake : NetworkBehaviour
{
    private SyncListInt syncListIntTest = new SyncListInt();

    private void Awake()
    {
        syncListIntTest.Add(5); //this causes error "SyncList not initialized"!!!!
    }

    private void Start()
    {
        syncListIntTest.Add(3); //this works fine without error
    }
}

Thanks in advance.

I’ve found Awake isn’t safe for other UNet things too, such as isServer. Though I noticed this before 5.2, and have generally adapted to use Start for any initialization reliant on the network.

Might be really handy to see an updated version of the Unity Execution Order doc, with UNet and UnityUI referenced.

(for reference: Unity - Manual: Order of execution for event functions)

1 Like

Thanks for the link. I agree that would be handy if manual was updated with UNet initialization orders.

http://docs.unity3d.com/Manual/UNetSpawning.html

see “Object Creation Flow”

Thanks for link. I agree with the object creation flow and I’m trying to do that, but running into “SyncList not initialized” errors when attempting to set SyncList values during Awake() on the server before spawning. See picture below. I’m not sure the proper way to handle this.

I’m still struggling with this.

If I set SyncList during Awake() it throws “SyncList not initialized” error
If I set SyncList with external initialization function (called immediately after instantiate) it throws “SendBytesToReady object TestPrefab(Clone) (UnityEngine.GameObject) has not been spawned” warning.
If I set SyncList during Start() the SyncList will not be set before spawning unless somehow I add a frame or two delay between instantiate and spawn.

What’s the proper way to set SyncList before spawning?

Thanks in advance.

So I’ve been doing some more testing and found something that works (although it throws error messages). My current flow is to.

1: Instantiate prefab on server
2: During prefab server Awake() method I set the SyncList (this throws “SyncList not initialized” errors… but functionally works just fine!)
3: Spawn prefab on clients (they get the proper SyncList values)

why do you need to use Awake? why cant it just be an initialization function you call on the object before it is spawned?

I tried an initialization function called externally to the prefab after Awake() but before Start(). This throws “SendBytesToReady object TestPrefab(Clone) (UnityEngine.GameObject) has not been spawned” warnings.

I am not sure why it is throwing warnings when setting SyncList before spawning, because that is the intended flow from my understanding.

Still struggling with this. Is anybody else using SyncList’s? If so how do you initialize the SyncList before spawning?

SyncValues don’t seem to initialize until OnStartClient is called, which is called after Awake but before Start (typically, anyway). I get around this by either creating my own “Init” function which I call OnStartClient, or by feeding the variables to another controller object for storage.

1 Like

Does OnStartClient call Init, or does your Init call OnStartClient? Do you mind pasting your code?

Ah, I posted the same code here, check it out: SyncList Callback only called when changed, but not when first transferred to the client - Unity Engine - Unity Discussions

1 Like

I put this info in:

public override void OnStartClient()
    {
}

and it get’s rid of your errors

1 Like

I am still having problems with this. OnStartClient() call is delayed and occurs after spawning (not before!).

I instantiate object and immediately spawn it. Adding debuggers shows things occur in this order on the server.

-Instantiate prefab on host
-Prefab.Awake()
-Spawn
-Prefab.OnStartClient()
-Prefab.OnStart()

I suppose maybe delaying the spawn (i.e. have it called OnStart) would work for instantiated objects. But how do you handle scene objects?

I think I figured out the proper order to initialize.

For SceneObjects
The order things are called
Server.Awake()
Server.OnStartClient()
Server.Start()
—at some point here the object is “Spawned” automatically on the client
Client.OnStartClient()
Client.Start()

SyncVars/SyncList should be set during Server.OnStartClient() or Server.Start(). If you set them during Awake() or through external initialization before OnStartClient then it causes errors. Even if the SyncVars/SyncList values are set during Server.Start() the correct values are replicated to the client by the time Client.Start() is called.

For SpawnedObjects the correct order seems to be
-Spawn prefab on server
-During server prefab Start() or OnStartClient() set the SyncVars/SyncList values
-At the end of server Start() call NetworkServer.Spawn(gameObject). Do NOT call spawn externally before prefab.Start() is called or the SyncVars/SyncList values will not be initialized.
-The SyncVars/SyncList values will be correct by the time Client.Start() is called.

That’s because unity sneakly add some code in Awake function to initialize synclist

so for your code, it will become

private void Awake()
  {
        syncListIntTest.Add(5); //this causes error "SyncList not initialized"!!!!
       this.syncListIntTest.InitializeBehaviour(this, ...);  // initialize here
  }
1 Like

Cool, fixed with 5.2.2p1
The “SendBytesToReady object TestPrefab(Clone) (UnityEngine.GameObject) has not been spawned” warnings. have been fixed

Am I missing something? How do you do an initialization function call on the object of SyncLists before it is spawned in? Or am I thinking too hard on this?

It seems that objects are spawned after Start() is called. So the order of events is something like this.

1: Host: Awake (tied/random)
1: Client: Awake (tied/random)
2: Host: Start
3: Host calls Spawn:
4: Client: Start

So if you initialize the SyncList during Host Start they will be the recent updated values when Client Start is called. I think

It’s all very finicky to get working right, but the 1 rule I have is don’t do ANYTHING during Awake(). Hope this helps.