How do I make a shared variable that can be edited by Clients?

(Using Unity Netcode for Gameobject v2.1.1)

Let’s say for example I want to make a button in the game that all players in a lobby can click, every time you click it, the score will increase by 1, and all players will share this same score, so like a clicker game but co-op I guess…

So I initially I tried to just have an int value on the server and then from the client increase it, so I tried using NetworkVariables to keep that synced number, but it turns out you cannot set it so it can be increased by clients.

So then I tried to make a ServerRpc that clients can call to have the server increase the number, but then I got a KeyNotFoundException, which I figured out was basically since I didn’t have a NetworkObject that is in the Network Prefab List and is spawned.

So I made the Start() void tell the server to spawn the NetworkObject, and from what I understood that was supposed to spawn it on all clients in the lobby, including the host and other non-host clients. This did spawn on the host and it worked fine, but when I joined on another client it wouldn’t be spawned.

This was probably because the new client joined AFTER the server spawned the NetworkObject, so I tried to basically make a new void that’d spawn the NetworkObject and use InvokeRepeating() to call it like every 5 seconds.

Now, on the Host, this spawned the NetworkObject properly but would then give errors every 5 seconds about the NetworkObject already being spawned and server trying to spawn it again, but this wasn’t disturbing the gameplay. However, on the Client the NetworkObject for some reason still wouldn’t be spawned ever. I waited for more than 5 seconds and nothing happened, and if I remember correctly no error showed up.

Now this might be expected or this might be me poorly setting up Hosting/Joining lobbies in which case I will try to work on that script, but I would like to know if this sort of behaviour is expected or not? Does the Server spawn the NetworkObject on all Clients by default and if not is it possible to make it do that?

I know that it’s probably unsafe to even want to make something like this and there are probably safer methods but this is an example question and I’m just trying to understand how this stuff works and if what I wanted to accomplish is even possible.

If you are using a client-server topology then the easiest way to handle that is have a NetworkVariable that has server write and everyone read permissions. Then clients would send “clicks” via RPC to the server (you can use SendTo.Authority or SendTo.Server).

If using distributed authority, then the same concept but you would need to make sure to use the SendTo.Authority as the target.

If you wanted to implement a form of reconciliation, then you would want to have each client send the network tick they clicked the button and the authority side (receiving the RPC) would order when each client contributed to the score based on the tick value sent. You could expand on the reconciliation direction a bunch…having a “window” of time (i.e. like every 6 ticks) that the authority reconciles “clicks” (and such).

1 Like

That is basically what I tried but I got a KeyNotFoundException error (Something like “Key not found in dictionary”) since the NetworkObject didn’t spawn on new clients, probably because they joined after server spawned it in Start(), so I used InvokeRepeating() to keep spawning it but it wouldnt work for clients still, and it gave me a "[Netcode] Failed to spawn locally… " error instead.

Is this because I didnt Instantiate the NetworkPrefab and instead had it in the scene to begin with and only ran NetworkObject.Spawn()? Is that not allowed?

I’m trying to understand right now how these NetworkObjects actually work in the first place.

Also as a side note, I didnt use the SendTo enum when calling RPC, and also RequireOwnership was false.

From the server side, you should subscribe to the NetworkManager.OnServerStarted event and when that is invoked you can start spawning NetworkObjects.

If this is an in-scene placed NetworkObject, then you shouldn’t have to spawn anything as it will spawn automatically when the server starts.

Would it be possible to prove me with your project (just the Assets and Packages folders are all I would need)?

1 Like

I ended up solving the problem somehow, I think there was something wrong with my code, but I’m not exactly sure what fixed it.

Thanks anyways, the responses did help with understanding how NetworkObjects and RPC works.