The server is an instance of the game that does all the network management, sending network packets (small portions of data) to client game instances that are connected to that server.
What will be sent to clients and what will remain on the server is on the programmer to decide, that’s what network programming is.
It guarantees every client game instance is seeing the game game, otherwise it would be analogue as seeing two different games being played in two different PCs.
Logic that will only run on the server game instance, so any information not networked from any clients are unknown to the server, we cannot just network everything, that's a lot of information to send over the network, we are here to manage what should be networked and what should not.
All the code run in the server, will only run on the server. If we were to set a variable on the server and not replicate that logic on the client, that means the client would never know that was changed.
[Server]
The Server attribute is used when we want to run methods only in the server.
Network messages are a way to transmit data without having to worry about object relationships, they are basically global events, which anyone can subscribe and listen to. And we can create structures to send whatever we want via the network.
The downside of that is that it doesn’t support late joins, the client has to be connected in order to receive that, otherwise it would miss the message. We should only use them when we want to ask something for the server to do, without worrying about object relations.
The client is a game instance that is connected to a server game instance, it receives all network packets the server wants to send it, so a character position is set by the server so every client sees your player in the same position.
Logic that will only run on the client game instance. Usually in Unity game development we use attributes for defining those rules, they are little tags that go above the method declaration, which does depend a lot on the networking framework you’re using in your game.
We are using FishNet Networking, the attribute is [Client], but code that is not sent to either clients or the server is always local to that game instance, so you only use that when you want to prevent the server game instance running that code.
[Client]
The client attribute prevents the server from running a method.
Continuing the disgrace, there’s code that the client decides when to run and the server actually executes it, with the information the client gave it.
This is probably one of the most critical parts when we think about security, we sometimes we have to trust the client with what they are sending the server, so extra validation can be welcoming.
Anyways the attribute is [ServerRpc] this one has another trick at its sleeve, we have to own the object that we are trying to call the method, this can however be completed ignored by using [ServerRpc(ignoreAuthority = true)].
To guarantee you got it right, the params of the call will use data from the client, and the logic will be executed with the server’s data.
In order to network stuff we need a framework. We aren't doing it from scratch (again). We used to use Mirror but I found FishNet Networking, and I haven't used anything else since. It has free and paid features, which is lame, but we can use it at our favour.
I'll add important notes about developing with in the next sections.
Usually here is where things get messy for some people, but for starters, the attribute is [ObserversRpc], RPC stands for remote-procedure-call, this one is called by the server, which means the server decides when to run it, and makes the client run it, with the information it wants.
That information is only valid for params, as the logic inside the code is run by the client, everything there only exists for the client, excepts for the method parameters sent by the server.