[NetCode] Expected amount of ghosts?

While playing around with the new NetCode package, I’ve set up an asteroid field spawner to test some limits. Each roid ghost has a renderer and physics, plus a rotate component used by a rotate system which runs in the server world.

I’m spawning 1000 of these on the server and letting the ghosts do their job, however have noticed the rate at which they get updated to the client is quite bad, I figure I’m hitting the packet size limit and the importance is kicking in, dropping some roids and coming back to them when they are a few frames old.

What is the expected number of ghosts the NetCode should handle? Have I done something wrong here? Are we supposed to be aiming for a tiny amount of ghosts - I thought projectiles were supposed to be ghosts too?

The number of ghosts the netcode can handle depends on their size, and how well they compress - which depends on quantization and predictability of updates. Scaling to large number of ghosts still requires carefully setting up the ghosts.

It sounds like you are hitting the bandwidth limit in this case. You can look at the stats for packets if you open the net debugger from Multiplayer > Open NetDbg (will open in a browser). You should be able to tell how big your ghosts are an how many you are sending each frame from there - which helps when trying to make them compress better.

If you want to scale to more ghosts than you can fit in a packet you need to setup distance based importance so the ghosts close to you get replicated more frequently than the things far away. See Ghost snapshots | Unity NetCode | 0.0.4-preview.0 . The implementation of it in asteroids is setting up the grid in https://github.com/Unity-Technologies/multiplayer/blob/master/sampleproject/Assets/Samples/Asteroids/GameMain.cs see GhostDistanceImportance. It also adds a GhostDistanceImportance when a connection goes in-game and updates it in https://github.com/Unity-Technologies/multiplayer/blob/master/sampleproject/Assets/Samples/Asteroids/Server/Systems/UpdateConnectionPositionSystem.cs

5 Likes

Thanks Tim, I figured distance based checks would be super important here.

Does anyone know what I should be setting TileCenter to here? Changing it doesn’t seem to make a difference in my tests. Also what does TileBorder do?

                var grid = entityManager.CreateEntity();
                entityManager.AddComponentData(grid, new GhostDistanceImportance
                {
                    ScaleImportanceByDistance = new PortableFunctionPointer<GhostDistanceImportance.ScaleImportanceByDistanceDelegate>(GhostDistanceImportance.DefaultScale),
                    TileSize = new int3(32, 32, 32),
                    TileCenter = new int3(0, 0, 16),
                    TileBorderWidth = new float3(1f, 1f, 1f)
                });

TileCenter offsets the grid a bit. Say you want 0,0,0 to be at the border of a tile instead of in the center of a tile, you would then set TileCenter to TileSize / 2. Unless you need fine grained control over the grid alignment you can just leave it at 0.

The tile border is related to reducing tile changes when an entity is between two tiles. The tiles are expanded by a border to have some overlap. This overlap means that you have to go a bit (the border size) outside your current tile before you switch to a new one, so if you are the the edge between two tiles and move a little bit back and forth you will not switch tile every frame.

3 Likes