Network Object
A Network Object is a GameObject with a Spatial Network Object component, and represents a single synchronized entity in a Spatial Space.
Network objects can either be embedded into a scene, or can be in Prefabs which can be instantiated at runtime.
Creating a Network Object
Scene Embedded Objects
The most basic way to make a GameObject networked is to add a SpatialNetworkObject
component to it in the scene. Scene-embedded network objects should be used for objects that are always present in the scene, like a game manager, doors with synchronized open/closed state. In other words, scene-embedded network objects should be considered "static" objects that never get destroyed. In fact, destroying a scene-embedded network object will log an error, and that destruction will not be replicated to other clients.
- Create a new GameObject in the scene.
- Add a
SpatialNetworkObject
component to the GameObject. - Customize its properties as needed (such as whether to sync transform, rigidbody, etc.).
- Additionally, you can attach any of your custom
NetworkBehaviour
components to the GameObject or its children.
The first actor to join the space will be the owner of any scene-embedded network objects.
Network Prefabs
Network Prefabs are unity prefabs that have a SpatialNetworkObject
component attached to the root GameObject. Network Prefabs can be spawned at runtime using the ISpaceContentService.SpawnNetworkObject
method and can have shorter lifetimes than scene-embedded network objects.
- First, create a new prefab in your project, edit it and add a
SpatialNetworkObject
component to the root GameObject. - Attach any custom
NetworkBehaviour
components to the GameObject or its children. - When the prefab is saved, it will be automatically registered in the Network Prefab Table where it will be assigned a unique
networkPrefabGuid
. This ID is used at runtime to identify the prefab when spawning it, so that both the local spawning client and the other remote clients can instantiate the same prefab. - Before we can spawn the prefab, we need to register it with the
Space Package Config
. This lets Spatial know which of the prefabs in the project are included in the space. To do this, add a new element to theNetwork Prefabs
list in theSpace Package Config
and drag the prefab into the slot. - Now you can use
ISpaceContentService.SpawnNetworkObject(networkPrefab, position, rotation)
to spawn the prefab at runtime.
When Network Prefabs (prefabs with a SpatialNetworkObject
on the root GameObject) are embedded in a scene, they will be treated as scene-embedded network objects.
Object Properties
Network Objects manage the synchronization of ownership, lifecycle, transform state, physics and custom state defined in NetworkBehaviour
components.
Object Flags
These flags control the ownership and lifecycle of the Network Object.
Flag | Description |
---|---|
MasterClientObject | Indicates that this object is always owned and controlled by the master client. Ownership is fixed and cannot be transferred. If the current master client leaves the server instance, ownership will be transferred to the newly elected master client. |
DestroyWhenOwnerLeaves | Indicates that this object should be destroyed when the owner of the object leaves the server instance. Can only be used with Network Prefabs. |
DestroyWhenCreatorLeaves | Indicates that this object should be destroyed when the creator of the object leaves the server instance. Can only be used with Network Prefabs. |
AllowOwnershipTransfer | Indicates that ownership of this object can be transferred to another client. |
Sync Transform
You can specify which transform properties to synchronize with the syncFlags
property. By default transform properties are not synchronized.
It is recommended to only synchronize the properties that are necessary for your use case. So for example, if you have a "GameManager" network object that simply needs to synchronize custom game state, you don't need to synchronize the transform properties of that GameObject. Typically, you would only synchronize the transform properties of GameObjects that move around in the scene at runtime.
All transform properties are synchronized in local space to its parent GameObject (transform.localPosition
, transform.localRotation
and transform.localScale
). This means that if a NetworkObject is reparented you may see desynchronization between clients.
Note
The transform parent of an object is not synchronized. Changing a NetworkObject's parent will only affect the local client. However, this can be implemented manually by synchronizing a NetworkObject.objectID property that is the parent and then finding the object by ID to parent it to.
Sync Rigidbody
If you want to synchronize physics properties like velocity, angular velocity, etc., you need to add a Rigidbody
component to the GameObject that has the SpatialNetworkObject
component, then enable the Rigidbody
flag under the syncFlags
property.
Only 3D rigidbodies are currently supported for synchronization.
Syncing physics is covered in more detail in the Network Physics section.
Spawning
You can spawn Network Objects by embedding them into a scene, or on-demand at runtime using the ISpaceContentService.SpawnNetworkObject method.
When a Network Object is spawned with ISpaceContentService.SpawnNetworkObject
, an instance is created using GameObject.Instantiate
on all clients. Immediately after that, it is "bound" to its network state (SpaceObject).
Before the object is bound it is not ready to be used in the networking context. Therefor, it is important not to have any network-setup logic in the MonoBehaviour.Awake
method, since that will be called before binding.
Note
Spawning Network Objects with GameObject.Instantiate
will simply create a local instance of the object and not replicate it to other clients.
Initialization Order & Lifecycle
Either the network object already exists in the scene, or is instantiated with GameObject.Instantiate
.
- After the instance is created,
Awake
is called on any components on the GameObject. - Spatial binds the object to its network state by assigning the
SpatialNetworkObject.spaceObject
property. SpatialNetworkBehaviour.Spawned()
is called on all behaviours associated with that Network Object. The order in which these calls happen will match the order in which the behaviours are added to the GameObject and its children. First any behaviours on the root GameObject, then any behaviours on its children starting from the top of the hierarchy.
Nesting
Network objects can be nested within other network objects. This is useful for creating hierarchies of objects that need to be synchronized together.
When a parent network object is spawned, all of its children are also spawned. When a parent network object is destroyed, all of its children are also destroyed. Destroying nested network objects at runtime is not supported and will not replicate to other clients.
Nested objects can have different owners, but their lifecycle is tied to the parent object.
Parenting
A Network Object's transform parent is not synchronized by default. Changing a NetworkObject's parent will only affect the local client.
You can however manually implement transform parent replication by syncing a NetworkObject.objectID
property and parent the object by finding the object by ID:
Finding Network Objects
Each spawned Network Object has a unique objectID
which is assigned at runtime when it is spawned. You can use this ID to find a Network Object using the ISpaceContentService.TryFindNetworkObject
method.
Object Identification
We use SpatialNetworkObject.sceneObjectGuid
and SpatialNetworkObject.networkPrefabGuid
to identify Network Objects across clients. These are baked in at editor time and these IDs are preserved between package versions to maintain network-compatibility.
These serve a different purpose than objectID
:
SpatialNetworkObject.**Guid
are used to identify source assets (prefabs or scene-embedded objects) across clients.SpatialNetworkObject.objectID
is used to identify instances of those assets.
Identification in Scenes
When a Network Object is embedded in a scene, either as a prefab, or as a basic GameObject, it will be assigned a sceneObjectGuid
that is unique to that object within the scene.
Network Prefab Table
When prefabs are saved that have a SpatialNetworkObject
component attached to the root GameObject, they are automatically registered in the Network Prefab Table. This asset is located at Assets/Spatial/NetworkPrefabTable.asset
and contains a list of all the prefabs that have been registered in the project.
Generally, you never need to interact with this asset directly, but it important to understand that this table is used to preserve network-compatibility between published package versions.
If you use version control for your project, make sure to commit this asset to your repository. If version control merge-conflicts arise, generally speaking you want to keep both changes, as they represent different prefabs.
Misc
Adding or Removing Behaviours at Runtime
Adding custom NetworkBehaviour
components at runtime is not supported. All network behaviours must be known at build time (in editor). This is because the network state of a Network Object is defined by the set of behaviours that are attached to it.
Similarly, removing network behaviour components at runtime is not supported. Destroying a Network Behaviour component will destroy it locally, but will not replicate that destruction to other clients.
Destroying Scene-Embedded Network Objects
Destroying scene-embedded network objects at runtime is not supported and will not replicate to other clients.
Scene-embedded network objects should be considered "static" objects that never get destroyed. If you need to destroy a scene-embedded network object, you should consider spawning it dynamically with a network prefab instead.
Destroying Nested Network Objects
When you want to destroy a network object, you should destroy the root GameObject that has the SpatialNetworkObject
component attached. This will destroy the entire hierarchy of nested network objects.
Destroying nested network objects at runtime will result in errors, and the destruction will not replicate to other clients.