node.jssocket.io

What is the most effective way to handle multiple objects independent from all players when making a game with sockets?


For example, let's say I have a random game in which I have 500 independent objects and 10 players.

Independent object is an object that moves in a specific direction per update regardless of what players do (there is no need for players to come into contact with these objects).

Now if a player is shooting (lets say) a bullet, it is easier because it belongs to a specific player therefore it's easier to avoid in game lag. Lets look at something simpler, though, for example a player try to update their position. The typical thing I would do on client & server side would be this :

    client side : update the coords of the player + send a message to the server as socket X

    server side : receives the message from socket X, updates the coords of the player on the server side + 
sends a message with the coords of that same player to all other sockets

When you do the communication like this, everyone will receive the new coords of the player and there will be little to no lag. (It is also sufficient for objects like bullets, because they are created upon firing a player event)

How do you handle 500+ independent objects that move in random directions with random speed all across the map and update them for all players efficiently? (Be aware that their velocity and speed can be changed upon contact with a player). What I've tried so far:

    1) Put all of the movement + collission logic on the server side & 
notifying all clients with a setTimeout loop & io.emit - 

Result : causes massive lag even when you have only 500+ objects and 4 connected players. All of the players receive the server's response way too slow

    2) Put all of the movement + collission logic on the client side & notifying the server about every object' position- 

Result : To be honest, couldn't encounter much lag, but I am not sure if this is the correct idea as every time an object moves, I am literally sending a message to the server from each client to update that same object (server is getting notified N[number of connected clients] amount of times about that same object). Handling this entirely on the client side is also a bad idea because when a player randomly switches tabs [goes inactive], no more javascript will be executed in that players' browser and this whole logic will break

I've also noticed that games like agar.io, slither.io, diep.io, etc, all of them do not really have hundreds of objects that move in various directions. In agar.io and slither you mainly have static objects (food) and players, in diep.io there are dynamical objects, but none of them move at very high speeds. How do people achieve this? Is there any smart way to achieve this with minimal lag?

Thanks in advance


Solution

  • Convert your user interactions to enumerated actions and forward those. Player A presses the left arrow which is interpreted by the client as "MOVE_LEFT" with possible additional attributes (how much, angle, whatever) as well as a timestamp indicating when this action took place from Player A's perspective.

    The server receives this and validates it as a possible action and forwards it to all the clients.

    Each client then interprets the action themselves and updates their own simulation with respect to Player A's action.

    Don't send the entire game state to every client every tick, that's too bloated. The other side is to be able to handle late or missing actions. One way of doing that is rollback where you keep multiple sets of state and then keep the game simulation going until a misinterpretation (late/missing packet) is found. Revert to the "right" state and replay all the messages since in order to get state to correct. This is the idea behind GGPO.

    I suggest also reading every article related to networking that Gaffer on Games goes into, especially What Every Programmer Needs To Know About Game Networking. They're very good articles.