Building a simple online game server for Unity

FlySoFast picture FlySoFast · May 28, 2015 · Viewed 28.4k times · Source

I'm trying to build an online game server for my Tank game 2D (Unity). In my game there will be 2-4 players control their tanks and fight each other.

  • I've tried to use Unity networking, it was not really suitable for my game because we have to choose 1 of the players in the room to become the "server", which is not really flexible for my future development (e.g. when the "server" quit, I have to do a lot of work to remain connections between the other players).

  • Then I've tried to build my own server with Nodejs là socket.io for server-client communication. It's very simple: receives data from one and broadcasts them to the others. It seems to work fine until the physics part comes in: the server must trust the clients when they say there's something being hit or explode, then broadcasts it to the other clients. Not to mention the cheated clients, with the network latency, the physics simulation of the clients will vary. For example, a tank might be hit on this client but it should be covered behind the wall on the other one and stay alive, but the tank behind him catches the bullet and explodes, because of the latency. In these cases the server doesn't know which one to listen to.

Update

  • As @Catwood mentioned below, Photon PUN is another option for me. I had followed one of their tutorials before. Photon doesn't need a player to be the "server" like Unity networking. But how do I implement my game logic on the server? (for authoritative server purpose)
  • Apparently Smartfoxserver is another good (and pricey) option. I haven't taken a deeper look at their API document. I'm don't know if I could implement my gaming logic and rules on this (their tutorial skip this part for the sake of simplicity).

In conclusion, I need a suggestion for my game server:

  • Is an authoritative server
  • Can handle game rules and decide what will happen (maybe should have its own physics engine)
  • Works well with Unity2D
  • Javascript, C#, Java are preferred!

Am I going the right direction, because seems like some game server services (such as Photon, Unity networking) just don't care about how to implement game logic on the server. And does it make them not an authoritative server?

I am very new to this field, anything will be appreciated!

Answer

Gary Olsson picture Gary Olsson · May 28, 2015

I would advise to create your own server for your game like you did with NodeJS. Most of the solution I know are quite hard to use and cannot do eveything you want to.

For example, Blizzard game's Hearthstone is based on Unity for the client and have a custom made server side.

Here are some advice on how to create your game server.

It seems to work fine until the physics part comes in: the server must trust the clients when they say there's something being hit or explode, then broadcasts it to the other clients.

When creating your server you must make every important decision server-side and not client-side. It is the server who start the party, so the server must have the following information

  • The size of the map
  • The number of player
  • Data about each player (Health point, position, size, attack speed...)
  • Any other information required to make decisions

Now, the client should always send very small signal to the server like the following

  • Move left
  • Join party
  • Shoot
  • Rotate right
  • etc...

Based on user's action and user's data, the server can run a "simulation" of the game.

  • Check if the action is allowed
  • If it's allowed, simulate the action. If it's not, put it in a queue
  • Send to users informations about what is happening (Player one hit, player two dies, player four moves left etc..)

With this, the server knows when something happens and decide what happens. You do not rely on client side information, you only recieve the player's desired actions.

However, as you said, because of latency and other network factors, your client cannot be too dependent of the server. In modern games, the client have the same data about the player than the server and do not always rely on the server to display on screen what is happening.

If you played some online games, you may have noticed that when a connection with the server is lost, there's a small amount of time during which you can continue to play (move, shoot, etc..) but nothing moves except you. This is because the client continue to "run" the game based on your action even without server's informations.

However, to avoid any huge difference between what is displayed by the client to the player and what is happening in the server's simulation, the client and the server "synchronize" at regular interval.

For example, if you decide to move left, the client knows your move speed so it can display the movement without relying on the server.

When the synchronization occurs, the server send to the client critical information and the client change any currently displayed informations with what the server send.

Whith the left movement example, if your movement speed is different on the server and on the client, when the client receives a synchronisation order, you'll notice that your player will be "teleported" from the displayed position to another. This can also occurs if some packet are lost or because of high latency.

Handling lantency is a huge challenge when creating an online game both on server and client side and it's not the topic of this question.

To summarize, your server should

  • be homemade
  • Only receive actions from clients
  • Simulate the game
  • Send clients information about what is happening
  • Synchronize at regular interval with clients

Hope this help =)


Here are some explanation on how to add logic inside your server. Small disclaimer before, I've never used NodeJS so I don't know if this is achievable using NodeJS, I usually use C++.

Now for your game, I'll assume that the player can only use the action MOVE.

When a user connect to you server, you can launch the game. Because your user can move, it means that there's a 2D map, that your user have a size and an initial position and a speed. So your server should start a new "GameParty" and initialize the above data. For the example, let's assume the following defaults value are set.

map_width = 512;
map_height = 512;
user_width = 2;
user_height = 2;
user_speed = 1;
user_posx = 20;  
user_posy = 20;

When a client wants to MOVE, he send a packet to the server saying he wants to move. You can use any protocol you want for client<->server communication, I use a binary protocal but let's say you use Json

{action: move; value: left};

With this, your server will know that the user wants to move to the left. So, you just have to decrease user_posx by the value user_speed to have, server side, your new position. If this position are on the edge of the map, you have two choice, making the user appear on the other edge of the map of forbid the action.

At regular interval of time, your server will send to the client the player's current position.