NetworkObject Parenting
Opt-OUT
This feature is behind a bool flag that can be toggled on the NetworkObject
inspector UI. It will be enabled by default but you can opt-out from it if you want to implement your own solution
MonoBehaviour.OnTransformParentChanged()
under NetworkObject
is utilized to catch transform.parent
changes.
Three additional state variables are stored in NetworkObject
:
A new virtual methodWe has been added ainto NetworkBehaviour
:
You need to consider two main code paths when synchronizing NetworkObject
parenting:
- At Object Spawn
- Client spawns objects including static scene objects and dynamic spawned objects on join.
- Serialize
NetworkObject
s with their payloads (such asNetworkBehaviour
s etc.) - Write
m_IsReparented
andm_LatestParent
fields to sync on the client-side
- During Gameplay
- When a valid
NetworkObject
reparenting happens during networked gameplay on the server-side, it is replicated across the network to the connected clients to sync - Write
m_IsReparented
andm_LatestParent
fields into aNetworkBuffer
and send that over to all connected clients withPARENT_SYNC
message type onMLAPI_INTERNAL
channel
- When a valid
Transform parent synchronization relies on the initial formation of transforms in the scene hierarchy being identical on all standalone instances.
#
NetworkObject Reparenting RulesA few basic NetworkObject
reparenting rules are listed below.
Limiting Non-Networked NetworkObject Transform Parenting
Rules outlined below are applied and enforced even while not networking (not hosting or connected). Specifically, if you were to try reparenting a NetworkObject
under a non-NetworkObject
, that'd be invalid and reverted even though you are not hosting or connected to a server.
#
Only A Server (or A Host) Can ReparentSimilar to Ownership, only the server (or host, which is both a server and a client at the same time) can control reparenting of a NetworkObject
in the network.
Clients however, can send RPCs to server and execute a logic server-side that ultimately makes server to reparent a NetworkObject
.
NetworkObject
(Or To The Root) Is Valid#
Only Reparenting Under A A NetworkObject
can only be reparented under another NetworkObject
(GameObject
with NetworkObject
component attached). Only exception is moving a NetworkObject
to the root of the scene hierarchy.
This is simply due to the fact that MLAPI would not be able to identify & locate new parent on the remote-side if it was a non-NetworkObject
parent. Again, except moving it to the root because we could identify no parent (root) scenario without NetworkObject
identification or scene hierarchy traversal.
#
Only Reparenting During Networking Is ValidA NetworkObject
can only be reparented while networking, in other terms you can only reparent while listening/running as a server.
If you allowed moves while not networking, you would be desynced immediately upon switching to networking. Also reparenting a NetworkObject
under a non-NetworkObject
while not networking would sound valid but that would not be replicable on the remote-side since Netcode does not cover full scene hierarchy synchronization.
NetworkObject
Back To Its Original Location#
Invalid Reparenting Will Move If an invalid/unsupported NetworkObject
parenting happens, Netcode will immediately pop it back to its previous location to keep things in sync and also will provide relevant error/warning messages to indicate the issue.
#
In-scene NetworkObject parenting of playersIn-scene NetworkObject parenting of players requires waiting for the client side NetworkSceneManager
generated SceneEventType.SynchronizeComplete
message to be received and processed as an event on the server in order for the server to make the connected player a child of an in-scene placed NetworkObject
. (For more informatiom on this see Real world In-scene NetworkObject parenting of players solution
#
(Re)Parenting Move ExamplesWe will assume that our initial scene hierarchy is looking like this:
So, let's try a few moves!
#
Root/Axe โ RightHand/AxeThis is a valid move because Axe (NetworkObject)
is being moved under RightHand (NetworkObject)
. We know about their NetworkObjectId
s and it will be replicated across the network to the clients by the server.
Now, our hierarchy is looking like this:
#
RightHand/Axe โ Body/AxeThis is an invalid move because Axe (NetworkObject)
is being moved under Body
which is not a NetworkObject
. It does not have a NetworkObjectId
and it can not be replicated and synced on the clients.
So, we tried to do this but it did not succeed:
We'd get an error message in the logs similar to this:
#
RightHand/Axe โ SceneRoot/AxeThis is a valid move because Axe (NetworkObject)
is being moved to the scene root (no parent). So even though there is no NetworkObjectId
to sync, empty/null parent can be synced across the network on the clients.
Our up-to-date hierarchy is now looking like this: