Code Design: Networking in Unity

Working with Unity has been a learning experience for the entire team, for every time I’ve been cursing it for something weird (like the LineRenderer) we’ve also been praising Unity for being awesome (the Particle System comes to mind). Personally this is the first time I’ve been working with a single game engine for this long and my prior knowledge is more towards the back-end side of things as I’ve mostly been working with XNA and SDL which aren’t game engines by their own right but libraries to create them.

Being more of a back-end programmer I wound up (voluntarily) with the goal to create the network part of Orbital Gear. Unity does have some great features with their NetworkView class, you can easily sync all the information inside a Transform, which takes care of the position, rotation and scale so it’s the same on all connected clients. The Transform syncing also has some settings on how to handle network lag and you can quite easily set up a game that has basic online play. So far so good, the NetworkView do have some design decisions, though, for Orbital Gear this has been how to set the member variables in all the clients while trying to take into account the possibility of massive lag and cheaters.

The obvious way to think is to use the NetworkView.OnSerializeNetworkView() that’s already in the NetworkView class, but it has some problems that we need to solve, namely that “It is automatically determined if the variables being serialized should be sent or received, see example below for a better description.” This fact present the problem that if the client decides what its member variables should be assigned to the possibility of cheating us only a step away for a programmer that knows his/her stuff as you can just change the value in the RAM via an external program or via DLL-injection and the other clients would just abide to that mindlessly. This has lead to our current solution which is to put most of the game logic on the server and update the clients accordingly, this resembles how popular games like League of Legends and Dota 2 does things, all your input is sent to the server, the server calculates and sends back the result.

1:  [RPC]  
2:  public void setHealth(float a_health) {  
3:    if (Network.isServer) {  
4:      networkView.RPC("setHealth", RPCMode.Others, a_health);  
5:    }  
6:    m_health = a_health;  
7:  }  

The game logic for setting health in Orbital Gear

 This code is designed to prevent setting health on a client and have it update on the other clients and the server, you can actually set the health on the client but no logic that reacts on your health is placed on the client so that would just bug out the health bar until the next time you get a health update from the server. The server will also have logic to prevent the remote procedure call from being called by the clients, in short, a lot of anti-cheat will be done server side in an attempt to ensure that games are being played in a fair way.

Unfortunately there is little hope to go entirely cheat-free in games, as long as they are run on a local machine there will be ways to cheat and modify it, part of the learning process will be to know how to handle cheaters.  Hopefully our approach will reduce the cheaters and the bandwidth need as this is not an evil scheme to impose some online-only DRM, joining a LAN server works just as fine as playing online and some single player game modes is in the plans, but that will wait until later 😉

– Joakim “Joxe” Clysén
Twitter: @Joxedin