Hi Guys,
I wanna send a List of bytes to every client and then every client reads this list and processes them. I have this Script:
public class ReceiveData : NetworkBehaviour, IDisposable
{
private NetworkList list1= new NetworkList();
//Method I will call from another script
[ServerRpc]
public void SendDataServerRpc(List posliste)
{
list1.Clear();
foreach (byte b in posliste)
{
list1.Add(b);
}
}
public override void OnNetworkSpawn()
{
list1.OnListChanged += CreateMap;
}
public override void OnNetworkDespawn()
{
list1.OnListChanged -= CreateMap;
}
public void CreateMap(NetworkListEvent changeEvent)
{
//How to pick every single list1 entry?
}
public void Dispose()
{
throw new NotImplementedException();
}
}
So my questions are:
Is it correct that the list1 will automatic synced when the foreach is done,because the list got changed?Or will it happen already if I clear the list, or after every Add in the foreach?
How do i get access to the individual elements in the received list in CreateMap()?
I get the error : SendDataServerRpc - Don’t know how to serialize System.Collections.Generic.List`1<System.Byte>. RPC parameter types must either implement INetworkSerializeByMemcpy or INetworkSerializable
How can I fix that?
If I want to create a new list and send it 5-6 times per second. Is it better to use a NetworkList or an RPC?
Sorry its my first time playing with multiplayer features. I am a bit confused
From what I can gather for what you’re doing you want a different approach here. Have a network list in a class owned by that client and have the network list permission set so that only the owner can write to it. Have the owner write the changes to the list and other clients pick them up.
OnListChanged returns a change event, use its Type field to determine the event, Index gives the position and Value the byte value. You may also need to check when the network objects spawns if there’s already data in the list. It’s possible if only changes are being added to the list later joining clients may miss earlier list changes.
From memory you can pass an array but not a list. You can convert the list to an array but I don’t think an rpc is necessary for what you’re doing.
Good question! For small amounts of data a network list’s probably fine, it depends, are all players playing on the same map, as that can save on having to send that large initial amount of data over.
For what it’s worth I thought about approaching the problem from a different angle. Create a minimap like camera and snapshot the playfield and send over any changes between snapshots. There are some problems with this approach, speed primarily and a potentially a lot of redundancy on a mainly static playfield. The volume data may also be an issue, at least on initial load. There’s other fiddly issues to work out but maybe I’ll look into it unless I get a hard no from someone with better knowledge on the subject.
In case it helps here’s an example Player class making use of a network list.
public class Player : NetworkBehaviour
{
NetworkList<SnapshotDelta> snapshotDeltas; // network lists can't be instantiated here, instead use Awake
private void Awake()
{
snapshotDeltas = new NetworkList<SnapshotDelta>(new List<SnapshotDelta>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
}
public override void OnNetworkSpawn()
{
Debug.Log("Player OnNetworkSpawn");
base.OnNetworkSpawn();
if(!IsLocalPlayer)
{
snapshotDeltas.OnListChanged += OnDeltaListChanged;
}
}
private void OnDeltaListChanged(NetworkListEvent<SnapshotDelta> changeEvent)
{
Debug.Log("Player OnDeltaListChanged: " + changeEvent.Type);
switch (changeEvent.Type)
{
case NetworkListEvent<SnapshotDelta>.EventType.Add:
// this is the event you'll most likely be using, unless you're persisting the whole playfield in the list
int index = changeEvent.Index; // the position of the added value in the list
SnapshotDelta snapshotDelta = changeEvent.Value; // the new value at the index position
break;
case NetworkListEvent<SnapshotDelta>.EventType.Insert:
break;
case NetworkListEvent<SnapshotDelta>.EventType.Remove:
break;
case NetworkListEvent<SnapshotDelta>.EventType.RemoveAt:
break;
case NetworkListEvent<SnapshotDelta>.EventType.Value:
break;
case NetworkListEvent<SnapshotDelta>.EventType.Clear:
break;
case NetworkListEvent<SnapshotDelta>.EventType.Full:
break;
default:
break;
}
Debug.Log("Player OnDeltaListChanged Recv Length: " + snapshotDeltas.Count);
}
public void SendSnapshotUpdate(List<SnapshotDelta> deltas)
{
snapshotDeltas.Clear();
foreach (var delta in deltas)
{
snapshotDeltas.Add(delta);
}
Debug.Log("Player SendSnapshotUpdate Local Length: " + snapshotDeltas.Count);
}
}