Sometimes you want to synchronize data outside of the current GameObject.
Out of the box, coherence offers you coherence offers you several options to synchronize data from your CoherenceSync objects' hierarchy:
Child GameObjects: when you need to network data directly from other GameObjects.
Child CoherenceSyncs: when you create a parent-child relationship of CoherenceSync objects at runtime.
Deep Child CoherenceSyncs: when you create a complex parent-child relationship of CoherenceSync objects at runtime.
CoherenceSync parent-child relationships on complex hierarchies
While the basic case of direct parent-child relationships between CoherenceSync entities is handled automatically by coherence, more complex hierarchies (with multiple levels) need a little extra work.
An example of such a hierarchy would be a synced Player Prefab with a hierarchical bone structure, where you want to place an item (e.g. a flashlight) in the hand:
Player > Shoulder > Arm > Hand
A Prefab can only have a single CoherenceSync
script on it (and only on its root node), so you can't add an additional one to the hand. Instead, you need to add the CoherenceNode
component to another Prefab so that it can be parented. Please note that this parenting relationship can only be set up in the scene or at runtime; you can't store it in the parent Prefab since that would break the rule of only one CoherenceSync
per Prefab.
To prepare the child Prefab that you want to place in the hierarchy, add the CoherenceNode
component to it (it also has to have a CoherenceSync
). In the example above, that would be the flashlight you want your player to be able to pick up. You don't need to make any changes to the Player Prefab, just make sure it has a CoherenceSync
script in the root.
This setup allows you to place instances of the flashlight Prefab anywhere in the hierarchy of the Player (you could even move it from one hand to the other, and it will work).
The one important constraint is that the hierarchies have to be identical on all Clients.
To recap, for CoherenceNode to work you need two things:
One or more Prefabs with CoherenceSync
that have some kind of hierarchy of child transforms (the child transforms can't have CoherenceSyncs on them).
Another Prefab with CoherenceSync
and CoherenceNode
. Instances of this Prefab can now be parented to any transform of the Prefabs with just CoherenceSync (in step 1).
CoherenceNode
works using two public fields which are automatically set to sync using the [Sync]
attribute.
The path
variable describes where in the parent's hierarchy the child object should be located. It is a string consisting of comma-separated indexes. Every one of these indexes designates a specific child index in the hierarchy. The child object which has the CoherenceNode
component will be placed in the resulting place in the hierarchy.
The pathDirtyCounter
variable is a helper variable used to keep track of the applied hierarchy changes. In case the object's position in the parent's hierarchy changes, this variable will be used to help settle and properly sync those changes.
Note: This is simply an example solution for a particular case which uses other tools coherence provides. Your project's needs might be different and require a different custom solution.
CoherenceSync direct parent-child relationships
Objects with the CoherenceSync
component can be connected to other objects with CoherenceSync
components to form a parent-child relationship. For example, an object can be linked to a hand, a hand to an arm, and the arm to a spine.
When an object has a parent in the network hierarchy, its transform (position and orientation) will update in local space, which means its transform is relative to the parent's transform.
A child object will only be visible in a LiveQuery if its parent is within the query's boundaries.
Creating an Entity hierarchy is very simple. All you need to do is add a GameObject with a CoherenceSync
component as a direct child of another GameObject with a CoherenceSync
component. You can add and remove parent-child relationships at runtime (even from the editor).
Destruction or disconnection of the parent object will also destroy and remove all children of this object. Those objects' state needs to be treated on the Client side to be reinstantiated on the next connection.
Sometimes, it is not practical to add CoherenceSync
objects to all the links in the chain. For example, if a weapon is parented to a hand controlled by an Animator, we do not need to synchronize the entire skeleton over the network. In that case, see CoherenceNode.
If the child object is using LODs, it will base its distance calculations on the world position of its parent. For more details, see the Level of detail documentation.
When the parent CoherenceSync
is destroyed, by default its CoherenceSync
children get destroyed together with it. This can be changed via the Preserve Children option on the parent:\
When the Preserve Children option is enabled, destroying the parent entity will result in children getting unparented instead of being destroyed together with the parent. Those children will now reside at the root of the scene hierarchy.
Binding to variables and methods within the hierarchy
When you have the Configure window open, it will show the variables, methods and component actions available for synchronization for your currently selected GameObject.
If the Prefab that you are configuring has a hierarchy, you can synchronize variables, methods and component actions for any of the child GameObjects within the hierarchy.
To do so, open the Prefab in Prefab Mode by clicking the Open Prefab option in the inspector. This will allow you to select any of the GameObjects that belong to the hierarchy, the Configure window will be updated automatically, showing you everything that is available to be synchronized.
To edit child GameObjects, make sure you click on them in the hierarchy. A Configuration window will pop up.