Send Ghosts with NetCode Using Relevancy
Code and workflows to send ghosts and clean up logs using GhostRelevancyMode
What you'll develop on this page

We will implement a system where only the ghosts near a player are sent. We will also clean some unnecessary logs.
Github branch link: https://github.com/moetsi/Unity-DOTS-Multiplayer-XR-Sample/tree/GhostRelevancyMode-and-Clean-Up
Ghost Relevancy Sphere
Network transmission
So far we've been working with 200 Asteroids. This means our server sends updates for 200 entities, which is a lot of data streams for SnapShots.
Because data and bandwidth are limited it is important to be mindful of what updates are sent from the server to the client. You should always think: is the most important stuff getting to the client?
The [GhostField] attributes on our ghost IComponentData is the data that gets sent over between clients and server through SnapShots. Dynamic ghosts automatically have their rotation and translation sent over (clients can also send data through RPCs and Commands).
If you remember GhostAuthoringComponent it is possible to optimize ghosts to be "static" (like our HighestScore and PlayerScore). This means the server does not send updates on Translation and Rotation (because they are static).
Our Asteroid, Player, and Bullet prefabs all are dynamic so they send updates of their Rotation and Translation.

Think of a super large map with many ghosted objects-- do you think it's important for the client to get all of the snapshot data of objects that are way across the map? Probably not. It is not efficient for the player to receive the Translation and Rotation SnapShot updates of entities that will never ever encounter the player. That would be an inefficient use of networking.
Try it out - go to ConvertedSubScene, then the GameSettings GameObject, and change the Number of Asteroids to 2000
Next, change the Level Size to 100x100x100
Then press Play, Host a game and take a look at the Asteroids

The client is having a tough time getting enough SnapShot updates to make the asteroids appear to be moving smoothly.
Ghost Relevancy
We are going to use the concept of a Player Relevancy Sphere so that only ghosts that are within a certain radius of the player will be sent to the player.
The server will check for the relevancyRadius field in GameSettingsComponent in PlayerRelevancySphereSystem. If it exists, it will take note of the position of each client and only send ghosts within that distance.
Let's update GameSettingComponent to have an additional field, relevancyRadius
Paste the code snippet below into GameSettingsComponent.cs:

Now we must also update SetGameSettingsSystem to pass through this new field
Paste the code snippet below into SetGameSettingsSystem.cs:

Next, create a new System inside the Server/Systems folder and name it PlayerRelevancySphereSystem
Paste the code snippet below into PlayerRelevancySphereSystem.cs:

Now let's go back to GameSettings in ConvertedSubScene and update Relevancy Radius to 40, save, and return to NavigationScene

Now, hit Play, host a game, move around, and keep an eye out on the scene view
Self-destruct and move around

Only those ghosts that are in proximity to the player appear near the user
As the player moves you can see the "sphere" of asteroids appearing and disappearing
Now with these updates, you can have bigger maps in your games and host a lot more players. The server still runs calculations on bullets and asteroids the player does not see (out of its radius), so bullets still will collide with "far-away" ghosts that the player does not see when the bullet was fired.
Our game UI updates based on updated ghost values
We updated GameSettingsComponent
We updated SetGameSettingsSystem
We created PlayerRelevancySphereSystem
Clean-up
You might sometimes notice an error regarding GhostDistancePartitioningSystem when hitting Quit Game. There are also some errors that appear when we we quit the game while MainScene is running.
We're now going to handle quitting the application (Quit Game) more gracefully.
Part of accomplishing this is that we will cycle all worlds on our ClientServerConnectionHandler deleting queries during the OnDestroy(). We will also disable GhostDistancePartitioningSystem when we hit Quit Game.
Paste the code snippet below into ClientServerConnectionHandler.cs:

Now let's clean-up some more by removing some unhelpful logs from certain scripts
In SendServerGameLoadedRpc remove "Server acted on confirmed game load"
In GameUIManager.cs (the custom Visual Element) remove "Clicked quit game"

Now to wrap-up this entire section, we are left with these networking outputs:
started listening for UDP broadcast (NavigationScene)
server listening on port (MainScene server launch)
client trying to connect to an IP and port (MainScene client launch)
"Error receiving data from UDP client:" (When NavigationScene calls .Stop() on UdpConnection) - This is the UDP client receive thread being stopped - We can hide errors entirely for production
We showed how to use GhostRelevancy but for people that are just opening up this tutorial and don't know what is going on they might be confused why it is so "empty" intially so let's change back our GameSettings
level width, height, depth = 40
Num Asteroids = 200
Relevancy Radius = 0
Finally, we will add an assembly definition
This is needed to use UI Toolkit if you haven't gone through this tutorial step-by-step
Add the following file to /Assets:
We updated our project so that it can handle Quit Games a bit more gracefully
We also removed unnecessary logs
We updated ClientServerConnectionHandler
We removed log from SendServerGameLoadedRpc
We removed log from GameUIManager "Quit game"
Github branch link:‌
git clone https://github.com/moetsi/Unity-DOTS-Multiplayer-XR-Sample/
git checkout 'GhostRelevancyMode-and-Clean-Up'‌
Last updated