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.
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.
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?
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.
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.
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?
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.
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();
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.
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.