1
\$\begingroup\$

I'm coding a very simple game Rust/Dayz like with Unity, and I'm using Forge Networking as network library.

A few days ago, I started to code the Loot system. The Loots in my game are Items that are instantiated in the game world (in other words, the items that are on the ground) and I was implementing the system that send and receive Loot data from and to the server (the server is fully authoritative).
I also created a LootSpawnManager class that contains, in a list, all the Loot spawned in a certain Loot spawn spot (so there is a LootSpawnManager for every spawn point of the Loots object).

In my game the server checks if a player is in a certain range from the Loot gameObject. If it is, then the server sends the Loot data through the network to the client, and the client with that data creates a Loot object and instantiates it in its world (scene).

For optimization (because checking if there are players in an area is a bit expensive), the LootSpawnManager has a list, with all the players nearby, that is refreshed every 4/5 seconds. So, for example (in the server) if a Loot is added to a LootSpawnManager (or a Loot already in the LootSpawnManager list has changed its properties) the server sends the data to the players that are in the LootSpawnManager's players list.

So far no problems. The issues come when a Loot doesn't belong to a LootSpawnManager. In the game there will probably be hundreds if not thousands of Loots that don't belong to a LootSpawnManager, so every single Loot would have to do its check every 4/5 seconds, and this will certainly kill server performance.

A solution to this problem could be to group near solitary Loots in a class similar to LootSpawnManager that has the player list for that zone. But I don't think that this will help, because there will be few cases in which a lot of Loots are near, although in the majority of cases there will be maximum 2-3 Loots. So the question is: are there any good performance solutions for this problem?

EDIT :
I didn't mentioned that the client doesn't have instantiated all the Loots that are in the server, and the players have instantiated only the Loots in a certain range from them. If they are too far from a Loot they delete it (I'm talking about the single client side, so deleting means deinstantiating the object, not removing it in the server) and, like I explained before, if they are nearby a certain range from a Loot, then the client has to wait for the server checks.

P.S. I hope my English is understandable (it's not my mother language) and that what I just wrote above is clear.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I think you need on the server a generalized subsystem that tracks/accelerates spatial queries for authoritative objects. Loot would be one of these where the loot is registered with the system. Objects would then be replicated to clients in range. Testing would be cheaper because the system accelerates it via spatial structure and multi-frame coherence. The objects on the server deemed near a player could perform authoritative actions and send results to clients as well.

From your comments you indicate that the world is a 3D-heightmap. You don't indicate number of players, but here is a basic rundown of how I would build a system:

Given that the size of the world is fixed, I would define a grid size (that will need to be tuned later for performance reasons). I would then start with a two-dimensional grid where each cell of the grid is a list of items in the grid. I can imagine that you might have an interface or base type for items in the grid to make things easy to start with.

Now we need to keep track of which cells to look at each frame - which cells are occupied by one or more players and need to be searched. There are two strategies here - you could simply iterate over each player and check the cell the occupy. Run the list of items in the cell and update them against the player. The problem I see here is that you would update an item twice if two people are in the cell, so you might need two steps: 1) maintain a dictionary of all the cells and a list of each player in the cell so you can iterate over the dictionary and update each cell regardless of number of people in it. 2) Run the list of players to update their relationship to the items in the cell.

I only consider a two-dimensional cell because most heightmaps can't support overhangs, so you can discard the z (height) dimension.

There are so many optimizations to be made here but I think starting out that way would help.

\$\endgroup\$
4
  • \$\begingroup\$ So you would suggest something similar to R-tree? \$\endgroup\$
    – Aerdna
    Commented Dec 6, 2015 at 22:23
  • \$\begingroup\$ It depends on the kind of environment you have - a quadtree or octree, regular grid, dynamic bounding volume, or what have you. \$\endgroup\$
    – Steven
    Commented Dec 6, 2015 at 22:46
  • \$\begingroup\$ My maps size can be very large (smaller maps could be 5 square km,larger could be up to 30 square km) (I didn't mentioned it, but I think that was obvious that my world is in 3 dimensions). The map is not dynamic, in the sense that doesn't change any of his heightmap value, the only things that are variable are the Loots that can spawn, despawn and change their original values. If you have the patience could you please make a little/simple example on how you would structure the system ? \$\endgroup\$
    – Aerdna
    Commented Dec 7, 2015 at 15:33
  • \$\begingroup\$ thank you very much, I think I'll implement something very similar to the system that you described. I could even run that in a background thread (that will manage all stuffs related to the Loot spawn/system). Again, thanks a lot for your answers :) \$\endgroup\$
    – Aerdna
    Commented Dec 7, 2015 at 18:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .