Ghosts and snapshots
Understand ghosts and snapshots in Netcode for Entities and how to use them to synchronize states in your multiplayer project.
Netcode for Entities also supports a limited form of remote procedure call-like operations (RPCs) to handle events. For more information about when to use ghosts or RPCs, refer to the comparison on the RPC page.
Ghosts
A ghost is a networked object in a multiplayer game.
- A ghost is owned by (and simulated by) the server. In other words; the server has final authority over all ghosts. The server may therefore spawn, destroy, and update ghost entities.
- Each client connected to the server has a copy of each relevant server ghost, and the client updates this representation by receiving snapshots sent by the server - once per network tick - which contains the current state of a subset of these ghosts. The client then presents the updated state of the ghosts to the rest of the game simulation on one of two timelines (see interpolation and client prediction), allowing ghosts to be smoothly rendered etc. Note, then; the client cannot directly control or affect ghosts, because the server has authority over the entire game simulation. Therefore, any modification the client makes to a ghost is considered a client prediction, and can (and will) be reverted when new, server authoritative snapshot data arrives.
When you create a ghost, you need to define how it's synchronized between client and server. For more information about how to spawn ghosts after defining them, refer to the Ghost spawning page.
Create a ghost
Create ghosts in the Unity Editor by creating a prefab with a GhostAuthoringComponent
.
The GhostAuthoringComponent
in the Editor has a small editor that you can use to configure how Netcode for Entities synchronizes the prefab. You must set the Name, Importance, Supported Ghost Mode, Default Ghost Mode and Optimization Mode property on each ghost, and we also suggest you set the MaxSendRate value to reduce absolute bandwidth consumption. Netcode for Entities uses the Importance property to control which entities it sends when there's not enough bandwidth to send all entities within a single snapshot (the size of each snapshot packet can be customized). A higher value makes it more likely that the ghost is sent.
The (optional) MaxSendRate property denotes the absolute maximum send frequency (in Hz) for ghost chunks of this ghost prefab type (excluding a few nuanced exceptions).
Important Note: MaxSendRate
only denotes the maximum possible replication frequency, and cannot be enforced in all cases. I.e. Other factors (like ClientServerTickRate.NetworkTickRate
, ghost instance count, Importance, Importance-Scaling, GhostSendSystemData.DefaultSnapshotPacketSize
, and structural changes etc.) will determine the final send rate.
Examples:
- A ghost with a
MaxSendRate
of 100Hz will still be rate limited by theNetworkTickRate
itself, which is 60Hz by default. - Similarly, a ghost with a
MaxSendRate
of 60Hz instantiated in a project with aNetworkTickRate
of 30Hz will be sent at a maximum of 30Hz. - As this calculation can only be performed on integer/whole
ticksSinceLastSent
ticks, a ghost with aMaxSendRate
in-between multiples of theNetworkTickRate
will be rounded down to the next multiple. E.g.NetworkTickRate:30Hz
,MaxSendRate:45
means 30Hz is the actual maximum send rate.
Supported Ghost Mode options
- All: This ghost supports both interpolation and prediction.
- Interpolated: This ghost only supports interpolation. It can't be spawned as a predicted ghost.
- Predicted: This ghost only supports prediction. It can't be spawned as an interpolated ghost.
Default Ghost Mode options
- Interpolated: Unity treats all ghosts that it receives from the server as interpolated.
- Predicted: Unity treats all ghosts that it receives from the server are treated predicted.
- Owner predicted: The ghost is predicted for the client that owns it, and interpolated for all other clients. When you select this property, you must also add a GhostOwner and set its NetworkId field in your code. Unity compares this field to each clients' network ID to find the correct owner.
Optimization Mode options
- Dynamic: The ghost is optimized for a small snapshot size when both changing and not changing.
- Static: The ghost isn't optimized for a small snapshot size when changing, but isn't sent at all when it's not changing.
Synchronize ghost components and fields
Netcode for Entities uses C# attributes to configure which components and fields to synchronize as part of a ghost.
You can use the following fundamental attributes:
Attribute | Usage | More information |
---|---|---|
GhostFieldAttribute |
Use the GhostFieldAttribute on a struct field or property to specify which component (or buffer) fields to serialize. Once a component has at least one field marked with [GhostField] , it becomes replicated and is transmitted as part of the ghost data. |
Serializing and synchronization with GhostFieldAttribute |
GhostEnabledBitAttribute |
Use the GhostEnabledBitAttribute on an IEnableableComponent struct definition to specify that the enabled bit for this component should be serialized. Once a component is flagged with [GhostEnabledBit] , its enabled bit becomes replicated, and is transmitted as part of the ghost data. |
GhostComponentAttribute |
GhostComponentAttribute |
Use the GhostComponentAttribute on a ComponentType struct definition to:- Declare for which version of the prefab the component should be present. - Declare if the component should be serialized for child entities. - Declare to which subset of clients a component should be replicated. Important: Adding a GhostComponentAttribute won't make your component fields replicate. You must mark each field with a GhostFieldAttribute individually. |
GhostComponentAttribute |
Snapshots
A snapshot is a representation of the state of all ghosts on the server for a given network tick. Netcode for Entities sends one snapshot to each connected client once per tick, at a rate defined by NetworkTickRate
(which can differ from the SimulationTickRate
). If the NetworkTickRate
is lower than the SimulationTickRate
, then Netcode for Entities creates a subset group of connections, and sends one snapshot to each connection in the subset. Then, on the next tick, it sends a snapshot to the next subset, and so on. This is referred to as a round robin approach because it distributes the GhostSendSystem
load across multiple SimulationTickRate
ticks.
Snapshot processing
The ghost snapshot system synchronizes entities, which exist on the server, to all clients. To improve performance, the server processes ghosts per chunk, rather than per entity. On the receiving client side, however, processing is done per entity. It's not possible to process per chunk on both sides because one set of entities in one chunk on the server may not correspond with the same set of entities in one chunk on the client. There are also multiple clients, each with their own entity-in-chunk layout.
Partial snapshots
When replicating a lot of ghosts (or ghost data), the per-tick snapshot data size is clamped to the upper Maximum Transmission Unit (MTU) limit. As a result, it's common and expected for a snapshot to only contain a subset of all ghosts. These snapshots are referred to as partial snapshots. Ghosts in chunks with the highest importance values are added first, and Netcode for Entities streams your large world a few ghost chunks at a time, instead of sending all of them at once in a huge packet. This is effectively an importance priority queue.
You can also use MaxSendRate
to reduce the number of ghost chunks which are even considered as part of each snapshot's importance priority queue, which can also reduce total bandwidth consumption.
You can change the maximum size of snapshots. Reducing the maximum size saves bandwidth at the cost of a higher relative header overhead and less usable data, while increasing it may cause multiple UDP packets to have to be sent per snapshot, which can increase the probability of packet loss.
Refer to the documentation on importance scaling for more details.
Snapshot visualization tool
To understand what's being sent over the network, you can use the Network Debugger snapshot visualization tool.
To open the tool, go to Multiplayer > Open NetDbg, and the tool opens in a browser window. It displays a vertical bar for each received snapshot, with a breakdown of key information about each snapshot.
For more information about a particular snapshot, select one of the bars.

Note
This tool is a prototype.