Building a simple online game server for Unity - unity3d

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 tried to build my own server with Nodejs là socket.io for server-client communication. It's very simple: receive data from one and broadcast 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 explodes, then broadcasts it to the other clients. Not to mention the cheating clients, with the network latency, the physics simulation of the clients will vary. For example, a tank might be hit on one client but it finds cover behind the wall on another one and stays alive, but the tank behind it 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 purposes)
Apparently Smartfoxserver is another good (and pricey) option. I haven't taken a deeper look at their API documentation. I 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 it should have its own physics engine)
Works well with Unity2D
Javascript, C#, Java are preferred!
Am I going in the right direction, because seems like some game server services (such as Photon, Unity networking) 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!

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.

There is an asset on the asset store called Photon that is an authoritative server. It is free too for non mobile devices. This will handle the first part of your question for sure.
This great Tutorial will help.

Related

UE4 Blueprint: Cannot get player "death" to replicate on clients, only on server

Unreal Engine 4.22.3 and it is a Listen Server
I feel confident in knowing which blueprints exist where and who owns what. It seems I just cannot wrap my mind about how to make the server replicate something that a client did, so I'd really appreciate some help in understanding this.
In the Player Controller BP I trace under the mouse cursor for other players, when I left-click. If it found a player character, I want to run the "death" event in the Player Character BP. The replication works fine, when it is run by the host, but when a client clicks on another player, the event is only happening client sided. I actually thought it should work, as I set it up.
How would I do this properly? I am pretty sure I must be doing something wrong here.
EDIT: When the client clicks his own character, the player "death" is actually replicated fine. Only when a client clicks a different character than his own, it is not replicated to the server neither to the other clients.
From Replicating Functions in Blueprints:
There are 3 primary types of replicated functions: Multicast, Run on Server, and Run on owning Client. Multicast functions should be called on the server, where they are executed, and then forwarded automatically to clients. Server functions are called by a client and then only executed on the server. Client functions are called by the server and then only execute on the owning client.
The PlayerController needs to call a Run on Server function, so that the server's version of that PlayerController can update the authoritative information, which is then sent back to all the clients via a combination of replicated properties and client functions (probably Multicast in this situation).

Game Architecture P2P joining mid game

I am writing my thesis about different game architectures and I have not found an answer to this one question I have. I have googled for hours but have not found an answer.
I was reading this article: https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/
And there is this paragraph talking about p2p limitations for games :
The final limitation occurs because of the way the game synchronizes by sending just the command messages which change the state. In order for this to work it is necessary for all players to start from the same initial state. Typically this means that each player must join up in a lobby before commencing play, although it is technically possible to support late join, this is not common due to the difficulty of capturing and transmitting a completely deterministic starting point in the middle of a live game.
As stated by the author that when having a p2p connection, then players should join a lobby before starting a game, not joining an ongoing game.
He says that it is because it is hard transmitting a completely deterministic starting point in the middle of a live game.
Can someone please tell me why is that? Is it because there might be too much data to transfer and it might create some latency problems or is there another problem?
The amount of data to be transferred is not really the biggest problem, but can definitely have an impact.
To make things a little simpler, I will give you an example on what should be done in a client/server model, i.e. players connect to a central server, which runs the game engine and sends the state of the game to the players' computers. The server's task, is to keep the clients view of the game as consistent as possible, i.e. player health/position, position of objects in the map, etc.
Let's assume that you have 7 players in the match, with an 8th looking to join the in-progress game. The server needs to ensure that the new player receive the current state of the game in a timely manner, which requires processing/network resources on the server. Not only this is challenging from a programming perspective, but it results in a spike in resource usage on the server, which can theoretically impact other processes as well as the current match itself.
In the case of a P2P game model, where the server is one of the players' machines, the issue regarding the network amplifies, as usually servers have better Internet connections compared to your average household. The above still stands.
In the case of a pure P2P model, where each machine communicates with each other directly (I don't think there are modern games that actually do this), this becomes a very challenging problem of maintaining consistency in a fully meshed distributed system.

low connectivity protocols or technologies

I'm trying to enhance a server-app-website architecture in reliability, another programmer has developed.
At the moment, android smartphones start a tcp connection to a server component to exchange data. The server takes the data, writes them into a DB and another user can have a look on the data through a website. The problem is that the smartphones very regularly are in locations where connectivity is really bad. The consequence is that the smartphones lose the tcp connection and it's hard to reconnect. Now my question is, if there are any protocols that are so lightweight or accomodating concerning bad connectivity that the data exchange could work better or more reliable.
For example, I was thinking about replacing the raw TCP interface with a RESTful API, but I don't really know how well REST works in this scenario, as I don't have any experience in this area.
Maybe useful to know for answering this question: The server component is programmed in c#. The connecting components are android smartphones.
Please understand that I dont add some code to this question, because in my opinion its just a theoretically question.
Thank you in advance !
REST runs over HTTP which runs over TCP so it would have the same issues with connectivity.
Moving up the stack to the application you could perhaps think in terms of 'interference'. I quite often have to use technical stuff in remote areas with limited reception and it reminds of trying to communicate in a storm. If you think about it, if you're trying to get someone to do something in a storm where they can hardly hear you and the words get blown away (dropped signal), you don't read them the manual on how to fix something, you shout key words such as 'handle', 'pull', 'pull', 'PULL', 'ok'. So the information reaches them in small bursts you can repeat (pull, what? pull, eh? PULL! oh righto!)
Can you redesign the communications between the android app and the server so the server can recognise key 'words' with corresponding data and build up the request over a period of time? If you consider idempotency, each burst of data would not alter the request if it has already been received (pull, PULL!) and over time the android app could send/receive smaller chunks of the request. If the signal stays up, just keep sending. If it goes down, note which parts of the request haven't been sent and retry them when the signal comes back.
So you're sending the request jigsaw-style but the server knows how to reassemble the pieces in the right order. A STOP word at the end tells the server ok this request is complete, go work on it. Until that word arrives the server can store the incomplete request or discard it if no more data comes in.
If the server respond to the first request chunk with an id, the app can use the id to get the response and keep trying until the full response comes back, at which point the server can remove the response from its jigsaw cache. A fair amount of work though.

what type of network programming is necessary in iPhone online multiplayer game?

I am asking this question as a small part of my question series regarding game programming .
Refer this question as the main one .
Now suppose I want to develop a game on iphone - a simple online multiplayer board game.
Suppose its a casino table.
In the main question ChrisF has tell me of sort of Client - Server architecture for iphone online multiplayer game.
I want to know what sort network programming I have to do for this type of application .
What will be the responsibilities and activities carried out by client and server .
You can provide me link, tutorials or to the point answers , anything will be great help for me and will be really appreciable .
thanks
You'll want to write a socket application running on a server. When you have access to a wifi access point or edge/3g you can send data to it from your iphone application. This server can then handle the incoming data and send an appropriate reply to the people connected.
For server socket programming, take a look at this guide - http://beej.us/guide/bgnet/.
For iphone specific socket programming, take a look at the samples supplied with the Iphone SDK. This link also has some basic information.
A simple online multiplayer board game
Given that the iPhone isn't always connected to the internet, you might need a server to store state. Alternatively you could always stipulate that if one person loses their connection the game finishes.
Client to client would be the obvious choice for the latter. Both clients have a port they listen to, and send the other commands based on the board state. Like almost all online games the obvious choice would be to use UDP as it's fast and compact.
For the server architecture you will of course need some kind of server listening for commands and a game number. It would store your state in a datastore on the server, a mySQL database for example. UDP or even SOAP or JSON over HTTP would be the two obvious choices for this.
This second approach using JSON/SOAP route would be a lot easier for you to get started with, assuming the iPhone has a decent JSON or SOAP library which is not likely. I have no idea about UDP in Objective C, however in C it requires a certain level of knowledge which won't get you something to play with quickly.
As you already said, you will need a server, but you can have two kinds of design:
The server can serve only as a gateway between the players to connect one to each other: it's two uses are, first, to list the running games, and second, to list the IP addresses of the players so that each client will read the IP addresses and connect to them. This will require less bandwidth and processing power for the web server and more for the client which will host the game. In this configuration, one of the clients will act as a server and will send data to the others. If your game has only one of the players playing at a time, and not a huge lot a players, this is what you should use as what you pay is the server's power.
The server can also store all games' states: it might require far more processing power and/or bandwidth depending on your game.
Anyway, most of the time you will want only one machine (which can change during the game as in the first case) to do the processing and the others will only receive the computed data.
To program a networked game, you will need knowledge of sockets (deep knowledge in the first case because you will have to deal with NAT issues, routers blocking the way between clients). The guide to that is Beej's Guide to Network Programming, the number one ressource on this topic, although it doesn't focus on games.
If not too much processing is needed on the WWW server, you could deal with it with server scripting languages like PHP along with MySQL, but you're most likely to use your own server programmed in C++ (or in C). If you use C++, you might want to use an already existing library such as RakNet.
The client will obviously be programmed in Objective-C as it's on the iPhone. I believe there is a good networking framework looking at the number of online games, so you might as well not want to use an external server networking library.
It might be a bit too much for what you want to do, but you could also use the well known Torque Engine.

What kind of issues are there in implementing realtime multiplayer games

I have some experience making multiplayer turn-based games using sockets, but I've never attempted a realtime action game. What kind of extra issues would I have to deal with? Do I need to keep a history of player actions in case lagged players do something in the past? Do I really need to use UDP packets or will TCP suffice? What else?
I haven't really decided what to make, but for the purpose of this question you can consider a 10-player 2D game with X Y movement.
'client server' or 'peer to peer' or something in between: which computer has authority over which game actions.
With turn based games, normally it's very easy to just say 'the server has ultimate authority and we're done'. With real time games, often that design is a great place to start, but as soon as you add latency the client movement/actions feels unresponsive. So you add some sort of 'latency hiding' allowing the clients input to affect their character or units immediately to solve that problem, and now you have to deal with reconciling issues when the client and servers gamestate starts to diverge. 9 times outta 10 that just fine, you pop or lerp the objects the client has affected over to the authoritative position, but that 1 out of 10 times is when the object is the player avatar or something, that solution is unacceptable, so you start give the client authority over some actions. Now you have to reconcile the multiple gamestates on the server, and open yourself up to a potentially 'cheating' via a malicious client, if you care about that sort of thing. This is basically where every teleport/dupe/whatever bug/cheat comes up.
Of course you could start with a model where 'every client has authority over 'their' objects' and ignore the cheating problem (fine in quite a few cases). But now you're vulnerable to a massive affect on the game simulation if that client drops out, or even 'just falls a little behind in keeping up with the simulation' - effectively every players game will end up being/feeling the effects of a lagging or otherwise underperforming client, in the form of either waiting for lagging client to catch up, or having the gamestate they control out of sync.
'synchronized' or 'asynchronus'
A common strategy to ensure all players are operating on the same gamestate is to simply agree on the list of player inputs (via one of the models described above) and then have the gameplay simulation play out synchronously on all machines. This means the simulation logic has to match exactly, or the games will go out of sync. This is actually both easier and harder than it sounds. It's easier because a game is just code, and code pretty much executes exactly the same when it's give the same input (even random number generators). It's harder because there are two cases where that's not the case: (1) when you accidently use random outside of your game simulation and (2) when you use floats. The former is rectified by having strict rules/assertions over what RNGs are use by what game systems. The latter is solved by not using floats. (floats actually have 2 problems, one they work very differently based on optimization configuration of your project, but even if that was worked out, they work inconsistently across different processor architectures atm, lol). Starcraft/Warcraft and any game that offers a 'replay' most likely use this model. In fact, having a replay system is a great way to test that your RNGs are staying in sync.
With an asynchronus solution the game state authorities simply broadcast that entire state to all the other clients at some frequency. The clients take that data and slam that into their gamestate (and normaly do some simplistic extrapolation until they get the next update). Here's where 'udp' becomes a viable option, because you are spamming the entire gamestate every ~1sec or so, dropping some fraction of those updates is irrelevant. For games that have relatively little game state (quake, world of warcraft) this is often the simplest solution.
There are a few factors involved in setting up multiplayer
The protocol, it's important that you decide whether you want TCP or UDP. UDP has less overhead but isn't guaranteed delivery. Conversely TCP is more trustworthy. Each game will have their preferred protocol. UDP for instance will work for a first person shooter but may not be suited for an RTS where information needs to be consistent
Firewall/Connection. Making sure your multiplayer game doesn't have to make 2000 outbound connections and uses a standard port so portforwarding is easy. Interfacing it with windows firewall will probably be an added bonus.
Bandwidth. This is important, how much data are you intending to push through a network connection? I guess this will come down to play testing and recording throughput. If you're requiring upwards of 200kb/s for each client you may want to rethink a few things.
Server Load. This is also important, how much processing is required by a server for a normal game? Do you need some super 8 core server with 16gb of RAM to run it? Are there ways of reducing it?
I guess there are heaps more, but really you want a game that is comfortable to play over the network and over a variety of connections.
Planning is your best friend. Figure out what your needs truly are.
Loading Data: Is every computer going to have the same models and graphics, and just names and locations are moved over the net. If every player can customize their character or other items, you will have to move this data around.
Cheating: do you have to worry about it? Can you trust what each client is saying. If not then you server side logic will look different than you client side logic. Imagine this simple case, each of your 10 players may have a different movement speed because of power ups. To minimize cheating you should to calculate how far each player can move between communication updates from the server, otherwise a player could hack there speed up and nothing would stop them. If a player is consistently a little faster than expected or has a one time jump, the server would just reposition them in the closest location that was possible, because it is likely clock skew or a one time interruption in communications. However if a player is constantly moving twice as far as possible then it may be prudent to kick them out of the game. The more math, the more parts of the game state you can double check on the server, the more consistent the game will be, incidentally this will make cheating harder.
How peer to peer is it: Even if the game is going to be peer to peer you will probably want to have one player start a game and use them as a server, this is much easier than trying to manage some of the more cloud based approaches. If there is no server then you need to work a protocol for solving disputes between 2 machines with inconsistent game states.
Again planning is your best friend Plan, Plan, Plan. If you think about a problem enough you can think your way through most of the problems. Then you can start thinking about the ones you haven't solved yet.
How important is avoiding cheating ?
[Can you trust any information coming from a client or can they be trusted and authenticated ?]
Object model
How are objects communicated from one machine to another ? How are actions carried out on an object ?
Are you doing client/server or peer to peer ?
Random Numbers
If you do a peer to peer then you need to keep them lock-stepped and the random numbers synchronized.
If you are doing client/server how do you deal with lag ? [dead reckoning ?]
There are a lot of non-trivial problems involved in network coding.
Check out RakNet both it's free to download code and it's discussion groups.
TCP is fine if your run on a LAN. But if you want to play online, you must use UDP and implement your own TCP-like layer: it's necessary to pass throw NAT routers.
You need to choose between Peer-to-peer or Client-Server communication. In Client-Server model, synchronisation and state of the world are easier to implement, but you might have a lack of reactivity online. In Pee-to-peer it's more complicated, but faster for the player.
Don't keep history of player action for game purpose (do it, but only for replay functionality). If you reach a point where it is necessary, prefer make every player wait.