LogoLogo
HomeOnline DashboardAPIDiscordForums
SDK 1.6
SDK 1.6
  • Welcome
  • Overview
    • Features
    • Roadmap
  • Getting started
    • Get the Unity SDK
    • Setup a project
      • 1. Scene setup
      • 2. Prefab setup
      • 3. Test your game locally
        • Local testing using builds
        • Local testing via Unity's Multiplayer Play Mode
        • Local testing via ParrelSync
      • 4. Test in the cloud
        • Deploy a Replication Server
        • Share builds
    • How to... ?
    • Single-player to multiplayer
    • Video tutorials
    • Samples and tutorials
      • Package samples
      • Sample Connection UIs
      • First Steps tutorial
        • 1. Basic syncing
          • 1.1 Animation parameters
          • 1.2 Sending commands
        • 2. Physics / Authority transfer
        • 3. Areas of interest
        • 4. Parenting entities
        • 5. Complex hierarchies
        • 6. Persistence
      • Campfire project
        • Game mechanics
        • Leveraging object pooling
        • Remote interactions: Chairs
        • Remote interactions: Trees
        • A unique object with complex state
        • Custom instantiation and destruction
        • Running a server-side NPC
        • Playing audio and particles
        • A simple text chat
      • Beginner's guide to networking
    • Troubleshooting
  • Manual
    • Unity Components
      • CoherenceSync
      • CoherenceBridge
      • CoherenceLiveQuery
      • CoherenceTagQuery
      • CoherenceGlobalQuery
      • CoherenceInput
      • CoherenceNode
      • PrefabSyncGroup
      • Order of execution
    • Networking state changes
      • Instantiate and Destroy Objects
      • Supported types
      • Messaging with Commands
      • Syncing child GameObjects
      • Animation
      • CoherenceSync references
      • [Sync] and [Command] Attributes
      • [OnValueSynced] Attribute
      • Creating your own syncable member
      • Custom Component Actions
      • Rigid Bodies
      • Interpolation
    • Authority
      • Authority transfer
      • Server-authoritative setup
    • Lifetime
      • Persistence
      • Uniqueness
      • Example: A global counter
    • Parenting network entities
      • Direct children CoherenceSyncs
      • Deeply-nested CoherenceSyncs
      • Nesting Prefabs at Edit time
    • Asset management
      • Instantiating from CoherenceSyncConfig
      • Instantiate via
      • Load via
    • Scene management
    • Multiple Connections within a Game Instance
    • Baking (code generation)
      • Conditional compilation
    • Replication Server
      • Rooms and Worlds
      • Replication Server API
    • Simulators (Servers)
      • Scripting: Client vs Simulator
      • Run local Simulators
      • World Simulators
      • Room Simulators
      • Simulator slugs
      • Build and Deploy
      • Command-line arguments
    • Client Connections
    • Optimization
      • Areas of Interest
      • Level of Detail (LOD)
      • Profiling
      • Simulation Frequency
    • Project Settings
    • Advanced topics
      • Big worlds
        • World Origin Shifting
        • Load balancing
      • Competitive games
        • Simulation Frame
        • Determinism, Prediction and Rollback
      • Team workflows
        • Version Control integration
        • Continuous Integration
      • Schema explained
        • Specification
        • Field settings
        • Archetypes
      • Code stripping
      • Replication Server CLI
      • Single-player gameplay
    • Scripting API
  • Hosting
    • Choosing where to host
    • coherence Cloud
      • Online Dashboard
      • Manage Worlds
      • Configure Rooms
      • Player Accounts
      • Game Services
        • Lobbies
        • Cloud Storage
        • Key-Value Store (Legacy)
      • APIs
        • Worlds
        • Rooms
        • Lobbies
        • Cloud Storage
        • Key-Value Store (Legacy)
    • Peer-to-peer
      • Implementing Client hosting
  • Support
    • Release notes
    • Glossary
    • Unreal Engine support
    • WebGL support
    • ECS / DOTS support
    • Known issues
    • Upgrade guide
      • Upgrade 1.5 -> 1.6
      • Upgrade 1.4 -> 1.5
      • Upgrade 1.3 -> 1.4
      • Upgrade 1.2 -> 1.3
      • Upgrade 1.1 -> 1.2
      • Upgrade 1.0 -> 1.1
      • Upgrade 0.10 -> 1.0
      • Upgrade 0.9 -> 0.10
    • Credit cost & pricing
    • Report a bug
Powered by GitBook
On this page
  • In this scene
  • How it's set up
  • Parenting the crate with CoherenceNode
  • Transferring authority

Was this helpful?

Export as PDF
  1. Getting started
  2. Samples and tutorials
  3. First Steps tutorial

5. Complex hierarchies

Last updated 1 month ago

Was this helpful?

Game characters and other networked entities are often made of very deep hierarchies of nested GameObjects, needing to sync specific properties along these chains. In addition, a common use case is to parent a networked object to the tip of a chain of GameObjects.

Let's see how to handle these cases.

|

  • A/D or Left/right joypad triggers: Rotate crane base

  • W/S or Left joystick up/down: Raise/lower crane head

  • Q/E or Left joystick left/right: Move crane head forward/back

  • P/Space/Enter or Joypad button left: Pick up and release crate

In this scene

This scene features a robotic arm that can be controlled by one player at a time. In the scene, a small crate can be picked up and released.

The first player to connect takes control of the arm, and other players can request it via a UI button.

How it's set up

To demonstrate complex hierarchies we choose to sync the movement of a robot arm, made of several GameObjects. In addition to syncing several positions and rotations, we also sync animation variables and other script parameters, present on child objects.

To sync the whole arm we use a coherence feature called deep bindings, that is bindings that are located not on the root object, but deeper in the transform hierarchy.

Select the RobotArm Prefab asset located in /Prefabs/Characters, and open it for editing. You will immediately notice a host of little coherence icons to the right of several GameObjects in the Hierarchy window:

These icons are telling us that these GameObjects have one or more binding currently configured (a variable, a method, or a component action).

Now open the coherence Configuration window, and click through those objects to discover what's being synced:

In addition to position and rotation, we also choose to sync the animation parameter ClawsOpen, and enable Animator.SetTrigger() as a Network Command. Finally we disable the Robot Arm script when losing authority (to disallow input).

This is the base of the robot arm, for which we only sync rotation:

We don't sync the rotation of every object in the chain, since the arm is equipped with an IK solver, which allows us to just sync the target (Two-Bone IK_target) and work out the rotation of the limb (robotarm_bottomarm and robotarm_toparm) on each Client:

By syncing all of these properties, we can have the robotic arm move in sync on all Clients, simply by translating the tip of the IK, and rotating the base of the crane. All of the bindings in this hierarchy are synced through the Coherence Sync component present on the Prefab's root object RobotArm.

As you can see, using deep bindings doesn't require any special setup: they are enabled in exactly the same way as a binding, a Network Command, or a Component action is enabled on the root GameObject.

Parenting the crate with CoherenceNode

The Path property displays the location in the hierarchy where this object will be inserted. It gets automatically updated by coherence every time the object is parented. Each number represents a child in the root object (and it's 0-based).

Once we have this component set up, parenting the object only requires calling Transform.SetParent() like any usual parenting operation, and setting its Rigidbody component to be kinematic.

When we do this, coherence takes care of propagating the parenting to other Clients, so that the crate becomes a child GameObject on every connected Client.

This code is in the RobotArmHand class, a component attached to the tip of our hierarchy chain: GrabPoint. In OnTriggerEnter we detect when the crate is in range, storing a reference to it in a variable of type Transform named grabbableObject.

This reference is set to sync:

When the player presses the key P (or the Left Gamepad face button), the referenced crate is parented to the GrabPoint GameObject.

Note that coherence natively supports syncing references to CoherenceSync and Transform components, and to GameObjects.

Even if the Robot Arm Hand script is disabled on non-authoritative Clients, it references the correct grabbed crate in the grabbableObject variable due to it being synced over the network. So when its authority disconnects, other Clients will already have the correct reference to the crate network entity.

This allows us to gracefully handle a case where, for instance, a Client picks up the crate and disconnects. Because both the crate and the robot arm have Auto-adopt Orphan set to "on", authority is passed onto another Client and they immediately have all the data needed to keep handling the crate.

Transferring authority

To move authority between Clients, we can use the UI in the bottom left corner. The button is connected to the Robot Arm Authority script on the ArmAuthoritySwapper GameObject, and it transfers authority on both the robot arm and the crate. This script takes care also of what happens as a result of the transfer, including setting the crate to be kinematic or not.

Is Kinematic is set as follows:

On the authority Client
On non-authoritative Clients

Is being held

true

true

Has been released

false

true

The code is in the RobotArmAuthority class. To detect whether it's currently being held, it's as simple as checking whether its Transform.parent is null:

crate.GetComponent<Rigidbody>().isKinematic = crate.transform.parent != null;

Remember you can use Tab/click the Gamepad stick to use the authority visualization mode. Try requesting authority from another Client while in this mode.

One important note: this sample describes deep parenting at runtime. For more information on edit-time deep parenting, see the page about .

As mentioned in the lesson about , parenting a network entity to a GameObject that belongs to a chain requires some setup. To be able to pick up the crate with the crane, we equip it with a CoherenceNode component:

Similarly to the crates in the , we don't just want the crate to automatically become non-kinematic when we have authority on it. We want the crate to stay kinematic when authority changes while it's being held by the arm.

Nesting Prefabs at Edit time
Parenting Entities
Deep bindings
Coherence Node
Physics lesson
The icons in the Hierarchy show the GameObjects that contain bindings.
The root syncs only Transform.position (by default) and animation.
The physical base of the arm syncs its rotation
The IK target syncs both position and rotation.
The end point of the arm syncs two variables of its Robot Arm Hand script, useful for the grabbing behavior.
Both the robot arm and the crate are currently simulated on this Client.