I've not been able to figure out essential networking code. (network variables)

Hello, I need to figure out how to do certain basic things with the unity multiplayer system. I’m trying to make a game where the server controls all the data, and gives selective access to some of it to clients. Clients wont ever set this data, but they should still be network variables (as far as I’m aware) to keep them synced and functional. Each player will have their own set of information (such as the current state of their board, their cards in hand, and the contents of their discard pile) as well as some more limited information about all opponents (like the number of cards in their opponent’s hand, and the number of cards in each spell they have on their board, but not their contents). My questions are:

How do I make sure each player creates their own info on join? I believe it’s each client creates network variables, but I could just be wrong here, so just in case, I’m putting this as one of the questions

How do I change each player’s data with the server individually? So that when a player sends a request such as “I’d like to play a card here” I can update their board state, update everyone else’s more limited view of their board state, and subtract an action point from them, or similar things. I don’t need that exact thing coded, I just need to know how to read and write to an individual player’s network variables(or whatever works better here)

How can I make the server control a specific script, that still works with client and server rpcs? When I tried just making it a separate script it gave me an error because it didn’t recognize the server RPC as a valid method (does not exist in current context error) I’ve looked through the docs for a few hours and just couldn’t answer the above two questions. Help would be appreciated, and I can clarify if I have not been clear enough. Thank you!

Network variables are synced between all clients. You cant have multiple network variables each for one client.
If you want to change information for a singe client you should use serverRPC and clientRPC (only for one client, not for all of them).
I think you got the error with the serverRPC because you used MonoBehaviour and not NetworkBehaviour.

I did network behaviour not monobehaviour, so I still don’t know what’s wrong there, but, if there’s no network variables per a player, then what’s the NetworkVariableReadPermission readPerm = NetworkVariableReadPermission.Owner for? In the read permissions section of the doc it says:

Owner: This means only the owner of the NetworkObject and the server can read the value.

  • This is useful if your NetworkVariable represents something specific to the client’s player that only the server and client should know about

  • This might be a player’s inventory or gun’s ammo count (etc.)

so, how is this actually used then? Also the reason I don’t want to just use server rpc and client rpc is to prevent desync issues, using network variables is the better solution if possible as far as I can tell

You can pass player info on connection and have the server pick it up on OnConnectionApproval, this is the most convenient way of doing it. Otherwise you can have the client wait for its Player network object to be spawned and rpc the player info to the server.

The network variable permissions will give you the desired behaviour you’re after, being able to spawn a network object like a card and only the Owner of the object sees the network variable values of the card.

If you’re just starting out here’s a couple of video’s that might be useful to you.

https://www.youtube.com/watch?v=stJ4SESQwJQ

https://www.youtube.com/watch?v=3yuBOB3VrCk

And Unity’s Bitsize samples: https://docs-multiplayer.unity3d.com/netcode/current/learn/bitesize/bitesize-introduction/

How would I do what you have said? You’ve answered my first question for sure, this is a way of doing it and it’s not terrible, but my second question, how to have the server refer to the client owned network variables, remains unanswered. I’ve tried looking through the videos but have not seen the answer to this question. Could anyone please let me know how to allow the server to refer to client owned network variables? For my third question of RPCs, I understand that’s more fitting for another thread, and I’ll just open that up, so it’s now out of scope here. All I’m looking for here is how to access those variables.

The key point I think you’re missing is the client is the owner of the object, not of the network variables, they’re still controlled by the server. You can have client control network variables but that’s not what you want. You want your network variables in your Card class for example declared like this:

    NetworkVariable<int> damage = new NetworkVariable<int>(0, NetworkVariableReadPermission.Owner, NetworkVariableWritePermission.Server);

So only the owning client (and server) can read, and only the server can write.

For rpc’s when the client makes a ServerRpc call that method call is run on the server’s ‘copy’ of that network object. So a ServerRpc called on the client’s Player object will be run on the server’s Player object.

The workflow for drawing a card would be something like this:

Client: DrawCardServerRpc()
Server: DrawCardServerRpc()

  • Remove card from player deck
  • Add Card to player hand
  • Spawn Card

Client: Card spawns, show card in player hand

That’s super simplified but hopefully provides a basic understanding.

I just saw your other post. To clarify the Player only has one script, there aren’t separate client and server scripts.

Okay, then the last question relavent to this is, when the player joins and their player object I’d created (is there/what is) the array that holds those? Since I’d be referring to each objects network variables. I also wasn’t trying client owned network variables, I just wanted clients to have their own created on join, which I now realize is simply done when the network object is created. Thanks for all the help so far!

You can get the network clients as a dictionary with NetworkManager.Singleton.ConnectedClients or as a list NetworkManager.Singleton.ConnectedClientsList.

From NetworkClient you can get the player with networkClient.PlayerObject.GetComponent<CardPlayer>().

I tend not to use those but create my own Client class and store the player object there.

Thanks for all the help! Do I marked this as resolved or something?

No problem and sure you can do.