As we saw on the previous article about Authoritative Servers, there are some games that might be affected by how things are being handled in a game. FPS games for example, would feel unresponsive in a Fully-Authoritative Server, the data from the inputs has to travel all the way to the server, then it has to be validated, the game logic has to be updated accordingly, then the server sends the updated response back to the user, and finally the client has to render these changes to the screen. All this loop can take a while, therefore we have to come up with different ways to handle some things in our games in order to make the most out of them.
Based on this loop, if we break things down a bit, we can delegate some responsibilities to the clients. However, doing this changes many principles that define an Authoritative Server, that’s why we call these: Non-Authoritative Servers.
The Server manages the game logic:
The server still has to manage anything that is not character related, this includes: Minions, NPCs, world updates, time, physics, etc.
THE Client Handles all its logic:
The client manages all the logic that is directly owned by it. All the character movements (self), shooting, abilities, and other actions. Manages all the user input and translates it into In-Game character actions.
The server still has the role of the central communication node. Every message sent over the network between every computer connected to the game goes through the server. i.e. If a user wants to send an in-game private message (if supported) to another user, this message has to go through the server first and then re-routed to the target user. There is no peer to peer communication.
DATA AND MESSAGE VALIDATION:
Even though the clients manage their own actions, everything still has to be validated by the server in order to be updated into the game. This means that the server has to be able to check the validity of the player’s actions and accept or decline these actions.
Having the client manage some things doesn’t mean the server is now an easier task. We still have to do most of the things on the server side, we’re just handling the user inputs directly on the client and then validating these inputs on the server.
We don’t need to validate all the data, in fact, if we trust our users, we don’t even have to validate any of their actions, which will make everything much faster and feel snappier. But, is it safe to trust our users? While not every person in the world is a hacker, and not every player is a cheater, not validating this info will make our client code very easy to hack and create cheats for our game. Depending on your point of view and philosophy regarding the type of game you’re producing, it might be the worst thing for the user-base or it could not matter that much.
Lets take CS:GO for example, its a highly competitive game that relies on extremely fast reaction times. This game has allowed the clients code to handle many things, and while it works as a great game experience, this has made it easier for many people to cheat “hack” the game. This hacky/cheater culture has created many problems, it is simply not fun to play with people who are cheating. This culture has degraded the whole CS:GO experience, and many users have stopped playing it simply because of this. Lets be honest, you play a game to have fun, and playing with an unfair disadvantage is not fun in any scenario.
We’ve been talking about these things with a dedicated server in mind, but we can also have the client and the server in the same application. Although this is the default way of connecting games with Unity’s Networking, and the way that most tutorials teach you how to use Unity’s Networking, I highly recommend to have the server and client as separate applications. When you launch your game, you might not want the server to be visible, you can always launch the server in an “invisible” way in the background, and then launch the client which will connect to this server.
This will not only help you keep everything much more organized but it will also allow you to improve and optimize the code for specific tasks. This would also help you when you want to launch your game to the public, and you want to keep the server safe and only share the client.
Many of the optimizations and approaches used in an Authoritative Server can also be used in a Non-Authoritative scenario, as long as they have nothing to do with the actual task that is being delegated to the client. We can include all the core things like optimizing the message, communication protocols, design patterns, object pooling, so on. Keep in mind that some of these could also be used in the client to optimize it’s code.
It takes a lot of trial and error to get to the amount of task delegation that is appropriate for our game. Don’t be afraid to try different things out, there is no “one and only way” to do things, and there can be many right ways to do the same thing. The more things you try, the more you learn, the more you can comprehend and optimize.
In the next article, we’ll be comparing both Authoritative-Server and Non-Authoritative Servers, their pros and cons. We will also talk about when and why to use each.