I am quite new to Unity and i can't find any logical answer to the behaviour i am seeing.
I have written a basic script such as :
public class PlayerPosition : NetworkBehaviour
{
private Dictionary<string, int> testDict = new();
[ServerRpc(RequireOwnership = false)]
private void HitServerRpc(string key, int value)
{
RefreshClientRpc(key, value);
}
[ClientRpc]
private void RefreshClientRpc(string key, int value)
{
testDict[key] = value;
foreach (var item in testDict)
{
Debug.Log($"Item in current dict {item}");
}
}
// Other logical code that calls only HitServerRpc().
}
I am using this script on my player Prefab
in a client / host situation.
I have one client and one host (server + client) for the test and the question.
My question is : Why testDict
has only one key and one value when at least 2 different keys and value were added through 2 different RPC calls, one from each client ?
The log Item in current dict
is shown only once even if the HitServerRpc()
was called on two different clients :
HitServerRpc("user1", 3)
HitServerRpc("user2", 4)
All clients should have testDict
equaled to : {{"user1", 3}, {"user2", 4}}
PS : Weirdest thing, i have tried to move the testDict
in a static class and update it internally inside the static class instead of the class handling the RPC calls, it now has the correct values on the host but still not on the client.
All clients should have testDict equaled to :
{{"user1", 3}, {"user2", 4}}
I see why you think that, but no! Each of those calls accordig to you comes from a different client -> and thus from/to a different instance of your PlayerPosition
.
Let's say as in your description you have two players user1
and user2
.
Each of these is calling HitServerRpc
on their respective local authority instance of PlayerPosition
. Which then gets relayed as a ClientRPC to the other connected clients but still only to their respective instance.
Trying to visualize this
user 1 Device Server user 2 Device
user 1 (local auth) ----> user 1 ----> user1
user 2 <---- user 2 <---- user 2 (local auth)
The result would be that the respective dictionaries are indeed synced, however, PlayPosition
belonging to user 1 would only know the key user1
and accordingly the other instance only have the user2
key.
So I think in your use case actually rather using a static would make sense. There is no need though to put it into a different class. You could use
private static readonly Dictionary<string, int> testDict = new();
so all the local instances of PlayerPosition
use the same dictionary instance.