SyncListStruct: SyncList not initialized

I have code which looks like this in a NetworkBehaviour:

  public struct WorldCell {
     public int x;
     public int y;
     public int terrain;

     public WorldCell(FlatHexPoint point, int terrain) {
       this.x = point.X;
       this.y = point.Y;
       this.terrain = terrain;
     }
   }
   public class SyncWorldCells : SyncListStruct<WorldCell> { }
   private SyncWorldCells syncWorldCells = new SyncWorldCells();

When I call anything on syncWorldCells (.Clear(), .Add()), I get the exception “SyncList not initialized”. I was referencing the scripting API, and it’s not clear what I’m missing. SyncListInt works fine.

http://docs.unity3d.com/ScriptReference/Networking.SyncListStruct_1.html

This appears to be a bug. If the derived class name doesn’t contain the string “SyncList”, it is not processed properly.

If you use “class SyncListWorldCells” it will work. I’ll file a bug.

That did the trick! Thanks! :slight_smile:

I sometimes forget that there’s a bunch of reflection voodoo going on under the hood. :wink:

Additional possible issue: when the specified callback is called in response to an OP_ADD operation, the index that I’m receiving is always 0, rather than the index of the new element. (Unsure if this applies to other operations.)

Add() always adds at the end of the list… so the index would always be size-1.

This is probably because the synclist add message does not include the index - since it is always added at the end… but it is a bit strange for the user.

Yeah, it is certainly simple enough to deal with, it’s just that the callback has an index parameter, and it surprised me that it wasn’t the right index. :slight_smile:

One last thing – when a client connects, the SyncList I have isn’t getting synced automatically, so the new client’s local version of the SyncList is empty. Is this intended behaviour?

SyncList contents are sent to client with other SyncVars on the object. they should be initialized.

Yes yes, of course it is! I just wasn’t receiving anything via the callback and didn’t handle the initial sync, which has already taken place by the time OnStartClient() has been called. :slight_smile:

Thanks!

Thank you both!

I didn’t know that the list’s name should start with SyncList, since it’s not in the documentation.

Saved my day!

Had the same issue. Extra addendum - this SyncList___ only works if it’s a subclass of the script attempting to use it for synchronization. The underlying struct does not need to be, however.

Not sure if this counts as a bug, so I’ve opened a feature request to remove at least this part of said requirement.

How did you get SyncList to sync I can’t get them to sync? I don’t understand what you did good sir.

I have prefixed my SyncListStruct class with SyncList, however it is not getting synced. I see things fine on the host, but the client side is null. Anybody got a working example of a SyncListStruct?

2 Likes

Will this type of behavior be changed in the future, so that it will not be strange to the users?

Did you ever solve this? I am experiencing the same issue. Where the synclist is null on the client.

Yes, I did. But I don’t remember off hand what fixed things. I am just leaving work now. If you don’t get things working in 16 hours from this post, ping me and I will try to put together a working example for you.

Hey guys,

I’m getting the same problem as the author, I’ve tried several things to fix this issue, but I can’t seem to get it to work.
This is my code atm, and I’m getting the error:

SyncList not initialized

The error comes when i try to Add() to the list.

    public struct PlayerInfo
    {
        public Team team;
        public string username;
        public int connectionId;
        public int avatarID;
        public float joined;
        public override string ToString()
        {
            return username + "_" + connectionId;
        }
    }
    public class SyncListPlayerInfo : SyncListStruct<PlayerInfo> { }

    [SerializeField]
    private SyncListPlayerInfo syncListPlayerInfo = new SyncListPlayerInfo();

Any help will be greatly appriciated.

Scrap that, I didn’t fix it. I still get the problem on the Client

SyncList not initialized

Still need help! :slight_smile:

I’m pretty sure it has to do with initializing it in the OnStartClient() or something other than Awake(). Try and test to see if there are other ways you can call the initialization process.

1 Like

I believe the issue here is to do with authority. The object in question is, on the client, a non authoritative object. The unity documentation does indicate that the a synclist is “synchronized from the server to clients”. The below may only be a work around but it has worked for my application.

I have solved this for my self by doing the following using DanielDollerup’s example in the below code.

    NetworkClient _client;
    const short PlayerInfoMessage = 1002;

    void Start()
    {
        _client = NetworkManager.singleton.client;
        NetworkServer.RegisterHandler(PlayerInfoMessage, UpdateVoxelToServer);
    }

    //........ some method
    PlayerInfo p = syncListPlayerInfo[value];
    p.team = Team.Red;
    TransmitValues(p);
    //.......

    [ClientCallback]
    void TransmitValues(PlayerInfo player)
    {
        PlayerInfoMessage p = new PlayerInfoMessage();
        p.player = player;
        _client.Send(PlayerInfoMessage, p);
    }

    class PlayerInfoMessage : MessageBase
    {
        PlayerInfo player;
        public PlayerInfoMessage() { }

        public override void Deserialize(NetworkReader reader)
        {
            player.team = reader.ReadByte(); //You will have to look at breaking this down to the Team struct but is is here for reference
            player.username = reader.ReadString();
            player.connectionId = reader.ReadInt32();
            player.avatarID = reader.ReadInt32();
            player.joined = reader.ReadSingle();

        }

        public override void Serialize(NetworkWriter writer)
        {
            writer.Write(player.team);//You will have to look at breaking this down to the Team struct but is is here for reference
            writer.Write(player.username);
            writer.Write(player.connectionId);
            writer.Write(player.joined);
        }
    }
;

Ran into this issue, also was getting the List object as null when a client joined up (when trying to register the CallBack).

The solution for me was to define the class being used as the List inside the scope of the NetBehaviour using that list. This isn’t ideal but it works.

    private class SyncListNetSprite : SyncListStruct<NetSprite> { }
    SyncListNetSprite _netSprites = new SyncListNetSprite();

    public override void OnStartClient() {
        _netSprites.Callback = NetSpriteListCallback;
    }

This worked. But I originally I had SyncListNetSprite defined else where (specifically, in the file with the associated struct NetSprite). That was causing the line where I subscribe to the callback event to throw a null reference exception.