Runtime Re-parenting
GONet supports runtime re-parenting of networked objects -- attaching a GONetParticipant to another at runtime (e.g., picking up items, mounting vehicles, attaching weapons). The system handles transform sync suspension, physics state management, and position guards automatically.
How It Works
When you call SetParent() on a GONetParticipant's transform, GONet detects the change via OnTransformParentChanged() and publishes a ReparentGONetParticipantEvent to all clients.
// Pick up an item — attach it to the player's hand
item.transform.SetParent(player.handBone);
item.transform.localPosition = Vector3.zero;
item.transform.localRotation = Quaternion.identity;
// Drop the item — detach from parent
item.transform.SetParent(null);GONet handles the rest: publishing the reparent event, suspending transform sync on the child, managing physics state, and ensuring late-joiners see the correct hierarchy.
Transform Sync Suspension
When a GONetParticipant is reparented under another syncing GONetParticipant, the child's position and rotation sync is automatically suspended. This prevents the child's world-space sync from fighting with the parent's transform sync.
- •Only transform sync is suspended -- All other synced values (health, ammo, custom fields) continue syncing normally.
- •Automatic resume on detach -- When the child is unparented, transform sync resumes automatically.
- •Configurable -- Controlled by EnableTransformSyncSuspensionForNestedGNPs (default: true).
Position Guard
When a child is attached to a parent, GONet stores the intended local offset and re-enforces it every frame. This prevents the child from drifting due to sync or blending applying stale world-space values.
- •Automatic -- Enabled by default via EnableReparentPositionGuard.
- •Per-instance opt-out -- Set disableReparentPositionGuard = true on instances that need to move relative to their parent (e.g., turrets that rotate).
- •Dynamic updates -- Call UpdateReparentGuardValues() to update the stored offset when the child's local position changes intentionally (e.g., turret rotation, attachment point changes).
Physics Auto-Management
When a child GONetParticipant has a Rigidbody, GONet automatically manages its physics state during reparenting:
On Attach
- • Rigidbody set to kinematic
- • Gravity disabled
- • Original state saved for restoration
On Detach
- • Original kinematic state restored
- • Original gravity state restored
- • Transform sync resumes
Controlled by AutoKinematicOnTransformSyncSuspension (default: true). See the Physics Synchronization page for more detail.
Client Drop Fix
When a client drops an object (detaches from parent), there is a brief window where the server's stale position could override the client's accurate drop position. GONet provides MarkLocalDropInitiated() to capture the client's position before sending the drop RPC, ensuring the object appears at the correct location.
Late-Joiner Support
Reparent events are persistent -- they are stored and replayed for clients that join mid-game. A late-joiner will see the correct parent-child hierarchy without any additional synchronization logic.
- •Self-cancellation -- If an object is reparented back to its original parent (a no-op), the reparent event is suppressed to avoid unnecessary replay.
- •Pending queues -- If a reparent event arrives before the target parent exists on the client, it is queued with a 30-second timeout and applied when the parent appears.
Configuration
| Setting | Default | Description |
|---|---|---|
EnableTransformSyncSuspensionForNestedGNPs | true | Suspend child transform sync when parented |
AutoKinematicOnTransformSyncSuspension | true | Auto-manage Rigidbody kinematic state |
EnableReparentPositionGuard | true | Guard against local position drift |
ReparentAutoPublishDelayFrames | 1 | Frames to delay before publishing reparent |
MaxReparentsPerSecondPerAuthority | 10 | Rate limit per authority |
PendingReparentTimeoutSeconds | 30 | Timeout for pending reparent events |
Design-Time Limitation
Important: Nesting GONetParticipants at design time (in the prefab hierarchy) is not supported. Always spawn objects independently and call SetParent() at runtime. Design-time nesting causes multiple known issues with GONetId assignment, sync ordering, and despawn propagation.
Next Steps
- →Physics Synchronization -- Dual time system, Rigidbody auto-discovery, and physics-gated sync.
- →Spawning & Pooling -- Network-aware instantiation and zero-latency spawning.
- →Event System -- ReparentGONetParticipantEvent and persistent event replay.