LogoLogo
⚠️ Outdated documentationGo to LatestHomeAPI
SDK 0.10
SDK 0.10
  • Welcome
  • Overview
    • What is coherence?
    • How does coherence work?
    • Rooms and Worlds
    • Features and Roadmap
    • Release Notes
    • Known Issues and Troubleshooting
  • Learning coherence
    • First Steps tutorial
      • 1. Basic syncing
        • 1.2. Animation parameters
        • 1.3. Sending commands
      • 2. Physics / Authority transfer
      • 3. Areas of interest
      • 4. Parenting entities
      • 5. Complex hierarchies
      • 6. Persistence
    • How to network...
      • Racing
      • Turn-based
      • First-Person Shooter
      • MMO
      • Fighting
  • Get started
    • Installation
    • Scene Setup
      • Sample UI
    • Prefab Setup: CoherenceSync
    • Local Development
      • Tips and Recommendations
    • coherence Cloud
      • Create a Free Account
      • Deploy a Replication Server
      • Share Builds
  • coherence SDK for Unity
    • Components
      • CoherenceSync
      • CoherenceMonoBridge
      • CoherenceLiveQuery
      • CoherenceTagQuery
      • Order of execution
    • Networking State Changes
      • Messaging with Commands
      • Hierarchies & Child Objects
        • Child GameObjects
        • Child CoherenceSyncs
        • Deep Child CoherenceSyncs
      • Animations
      • CoherenceSync References
      • [Sync] and [Command] Attributes
      • [OnValueSynced] Attribute
      • Supported Types
      • Player Name (Sample UI)
    • Baking (Code Generation)
    • Authority
      • Authority transfer
      • Server-authoritative setup
    • Lifetime
      • Persistence
      • Example – a global counter
    • Optimization
      • Simulation Frequency
      • Areas of Interest
      • Level of Detail (LOD)
    • Interpolation
    • Settings
    • Simulation Frame
    • Replication Server
    • Simulators
      • Scripting: Client vs Simulator
      • Local Development
      • World Simulators
      • Room Simulators
      • Simulator Slugs
      • Multi-Room Simulators
      • Build and Publish
      • Command-line arguments
      • Load Balancing
      • Network Connectivity
    • Client Connections
    • Rollback Networking Support
    • Floating Origin
    • CLI
  • coherence API
    • Worlds
    • Rooms
    • PlayResolver
    • DescriptorProvider
  • Developer Portal
    • Overview
    • Dashboard
    • Worlds
    • Rooms
    • Game Services
      • Account
      • Key-Value Store
      • API
        • Game account
        • Key-value store
  • Schema explained
    • Overview
    • Specification
    • Field settings
    • Archetypes
  • Additional resources
    • Community
    • SDK Upgrade Guide
    • Video Tutorials
    • Quick Samples
    • Continuous Integration
    • Unreal Engine Support
    • WebGL Support
    • Peer-to-Peer Support (P2P)
    • Pricing
    • SLA
    • Glossary
Powered by GitBook
On this page
  • Creating a custom DescriptorProvider
  • Creating a custom Binding

Was this helpful?

Export as PDF
  1. coherence API

DescriptorProvider

Extending what can be synced from the Configure window

This is an advanced topic that aims to bring access to coherence's internals to the end user.

The Configure window lists all variables and methods that can be synced for the selected Prefab. Each selected element in the list is stored in the Prefab as a Binding with an associated Descriptor, which holds information about how to access that data.

By default, coherence uses reflection to gather public fields, properties and methods from each of the Prefab's components. You can specify exactly what to list in the Configure window for a given component by implementing a custom DescriptorProvider. This allows you to sync custom component data over the network.

Take this player inventory for example:

using UnityEngine;

public class Inventory : MonoBehaviour
{
    [System.Serializable]
    public class Item
    {
        public int id;
        public string name;
        public int durability;
    }

    public Item[] items = new Item[]
    {
        new Item {id = 0, name = "Shield", durability = 80},
        new Item {id = 1, name = "Stick", durability = 50},
        new Item {id = 2, name = "Stone", durability = 100},
    };

    public Item GetItem(int id)
    {
        foreach (var item in items)
        {
            if (item.id == id)
            {
                return item;
            }
        }

        return default;
    }
}

Since the inventory items are not immediately accessible as fields or properties, they are not listed in the Configure window. In order to expose the inventory items so they can be synced across the network, we need to implement a custom DescriptorProvider.

Creating a custom DescriptorProvider

The main job of the DescriptorProvider is to provide the list of Descriptors that you want to show up in the Configure window. You can instantiate new Descriptors using this constructor:

public Descriptor(string name, Type ownerType, Type bindingType, bool required=false)
  • name: identifying name for this Descriptor.

  • ownerType: type of the MonoBehaviour that this Descriptor is for.

  • bindingType: type of the ValueBinding class that will be instantiated and serialized in CoherenceSync, when selecting this Descriptor in the Configure window.

  • required: if true, every network Prefab that uses a MonoBehaviour of ownerType will always have this Binding active.

If you need to serialize additional data with your Descriptor, you can inherit from the Descriptor class or assign a Serializable object to Descriptor.CustomData.

Here is an example InventoryDescriptorProvider that returns a Descriptor for each of the inventory items:

using System.Collections.Generic;
using Coherence.Toolkit;
using Coherence.Toolkit.Bindings;

[DescriptorProvider(typeof(Inventory))]
public class InventoryDescriptorProvider : DescriptorProvider
{
    public override List<Descriptor> Fetch()
    {
        // Call base.Fetch to include public fields, properties and methods
        var descriptors = base.Fetch();

        var inventory = Component as Inventory;

        foreach (var item in inventory.items)
        {
            var inventoryDescriptor = new Descriptor(name: item.name, ownerType: typeof(Inventory), bindingType: typeof(InventoryBinding));
            inventoryDescriptor.CustomData = item.id;
            descriptors.Add(inventoryDescriptor);
        }

        return descriptors;
    }
}

To specify how to read and write data to the Inventory component, we also need a custom binding implementation.

Creating a custom Binding

A Descriptor must specify through the bindingType which type of ValueBinding it is going to instantiate when synced in a CoherenceSync. In our example, we need an InventoryBinding to specify how to set and get the values from the Inventory. To sync the durability property of the inventory item, we should extend the IntBinding class which provides functionality for syncing int values.

using Coherence.Toolkit.Bindings;
using Coherence.Toolkit.Bindings.ValueBindings;
using UnityEngine;

public class InventoryBinding : IntBinding
{
    public override string BakedSyncScriptGetter => "GetItem(ItemId).durability";
    public override string BakedSyncScriptSetter => "GetItem(ItemId).durability = @";

    // Required constructor signatures
    public InventoryBinding(Descriptor descriptor, Component unityComponent) : base(descriptor, unityComponent) { }
    public InventoryBinding() { }

    public int ItemId => (int)descriptor.CustomData;

    public override int Value
    {
        get => ((Inventory) unityComponent).GetItem(ItemId).durability;
        set => ((Inventory) unityComponent).GetItem(ItemId).durability = value;
    }
}

For the full list of supported binding types, see Supported types in Commands and Bindings.

We are now ready to sync the inventory items on the Prefabs.

Last updated 2 years ago

Was this helpful?

The Inventory component does not expose the inventory items by default.
The Inventory items can now be synced across the network.