# Welcome

Games are better when we play together.

**coherence** offers the tools[^1] and infrastructure[^2] to create multiplayer games with <i class="fa-unity">:unity:</i> Unity.

> Our mission is to give any game developer, regardless of how technical they are, the power to bring their games online.

***

If this is your **first time** exploring coherence, the Getting Started section. It covers installation and setting up a minimal project online.

{% content-ref url="/pages/oWkQnwpr5XAXYgJXVTDY" %}
[Installation](/2.3/getting-started/installation)
{% endcontent-ref %}

Once you grasp the basics and are looking for more comprehensive material, check out our sample content. It offers playable projects and ready to use samples.

{% content-ref url="/pages/UJ0A2SJghzTKTJC56uhF" %}
[Samples and tutorials](/2.3/getting-started/samples-and-tutorials)
{% endcontent-ref %}

If you're already working with coherence and want to take the most out of it, refer to the manual section, which cover all major features we offer.

{% content-ref url="/pages/HzSHyXeglfRzbRv3SlE9" %}
[Manual](/2.3/manual/networking-state-changes)
{% endcontent-ref %}

{% hint style="info" %}
Our team can answer all your questions. Find us on [Discord](https://coherence.io/discord), or if you prefer, reach out by [e-mail](mailto:devrel@coherence.io).
{% endhint %}

![](/files/-MYdFT1_1Ocrbqga02t7)

[^1]: coherence provides a package for Unity that integrates seamlessly within the Unity Editor.

[^2]: We offer coherence Cloud — a scalable and cost-effective service to host your game, handle player accounts, lobbies, and other backend-related mechanisms.


# Overview

**coherence** is a network engine, platform, and a series of tools to help anyone create a multiplayer game.

<div data-full-width="false"><figure><img src="/files/TVijpV9Vh0Wvnje3V9MS" alt=""><figcaption><p>A game topology where 3 clients and 2 Simulators are connected to a coherence Replication Server</p></figcaption></figure></div>

Our **network engine** is our foundational tech. It works by sharing game world data via the [Replication Server](/2.3/manual/replication-server) and passing it to the connected Clients. The Clients, in this context, can be regular game Clients (where a human player is playing the game) or a special version of the game running in the cloud, which we call "Simulator".

While coherence's network engine is meant to be [game engine agnostic](#user-content-fn-1)[^1], at the moment we only offer an SDK for Unity. We're hoping to change this in the future.

The **coherence Unity SDK** provides a suite of tools and pre-made Unity components, and a designer-friendly interface to easily configure [network entities](#user-content-fn-2)[^2]. It also takes care of generating netcode[^3] via a process called "Baking". In fact, simple networking can be setup completely without code.

But coherence is not just an SDK.

The [**coherence Cloud**](/2.3/hosting/coherence-cloud) is a **platform** that can handle scaling, matchmaking, persistence and load balancing, all automatically. And all using a handy [Dashboard](/2.3/hosting/coherence-cloud/online-dashboard). The coherence Cloud can be used to launch and maintain live games, as well as a way to quickly test a game in development together with remote colleagues.

For more information about how a network topology is structured in coherence, check out this video:

{% embed url="<https://www.youtube.com/watch?v=EpIlyg164w8>" %}

## Important concepts

### [Replication Server](/2.3/manual/replication-server)

A lean and performant smart relay that keeps the state of the world, and replicates it efficiently between various Simulators and game Clients.

The Replication Server usually runs in the [**coherence Cloud**](/2.3/hosting/coherence-cloud), but developers can start it locally from the command line or the Unity Editor. It can also be run on-premise, hosted on your servers; or be hosted by one of the Clients, to create a [peer-to-peer](/2.3/hosting/client-hosting) scenario (Client-hosting).

### [Simulator](/2.3/manual/simulation-server)

A special version of the Game Client without graphics (a "headless client"), optimized and configured to perform server-side simulation of the game world. When we say something is simulated "server-side", we mean it is simulated on one or several Simulators.

### Game Clients

A regular build of the game. To connect to coherence, it uses our[ **SDK**](/2.3/getting-started/installation).

Clients (and Simulators) can define [areas of interest](/2.3/manual/optimization/areas-of-interest) (Live Queries), levels of detail, varying simulation and replication frequencies and other [optimization techniques](/2.3/manual/optimization) to control how much bandwidth and CPU is used in different scenarios.

### [**Baking**](/2.3/manual/baking-and-code-generation)

This is the process of [generating code](/2.3/manual/baking-and-code-generation) specific to the game engine that takes care of network synchronization and other network-specific code. This is also known as "baking", and it's a completely automated process in coherence, triggered by just pressing a button. You can however [configure it](/2.3/manual/advanced-topics/schema-explained) for very advanced use cases.

### [coherence Cloud](/2.3/hosting/coherence-cloud)

An easy-to-manage platform for hosting and scaling the backend for your multiplayer game. The coherence Cloud can host a Replication Server, but also Simulators.

In addition, every project can have a showcase page where you can host [WebGL builds](/2.3/support/webgl)!

### [Online Dashboard](/2.3/hosting/coherence-cloud/online-dashboard)

Our cloud-backed dashboard, where you can control all of the aspects of a project, configure matchmaking, Rooms, Worlds, and keep an eye on how much traffic the project is generating.

{% hint style="success" %}
For more coherence terminology, visit the [Glossary](/2.3/support/glossary).
{% endhint %}

[^1]: That is not specific to any particular engine.

[^2]: An object in the simulation that is visible to all connected Clients, and whose properties are synchronised over the network.

[^3]: The part of the code of a game in charge of defining how networking behaves.


# Features

* Fast network engine with cloud scaling, state replication, persistence and auto load balancing.
* Easy to **develop**, **iterate** and **operate** connected **games** and **experiences.**
* SDK allows developers to make multiplayer games using Windows, Linux or Mac, targeting desktop, console, mobile, VR or the web.
* Game engine plugins and visual tools will help even non-coders create and **quickly iterate** on a connected game idea.
* Scalable from **small games** to **large virtual worlds** running on hundreds of servers.
* Game-service features like [**user account**](/2.3/hosting/coherence-cloud/authentication-service-player-accounts) and [**key-value stores**](/2.3/hosting/coherence-cloud/game-services/key-value-store).

### Network engine

At the core of **coherence** lies a fast network engine based on bitstreams and a data-oriented architecture, with numerous optimization techniques like delta compression, quantization and [network LOD-ing](/2.3/manual/optimization/level-of-detail-lod) ("Level of Detail") to minimize bandwidth and maximize performance.

### Authority models

The network engine supports multiple [authority](/2.3/manual/networking-state-changes/authority) models:

* Client authority
* Server authority
* Server authority with client prediction
* Authority handover (request, steal)
* Distributed authority (multiple simulators with seamless transition)
* Deterministic client prediction with rollback (*"*[*GGPO*](https://en.wikipedia.org/wiki/GGPO)*"*) - **experimental**

Different authority models can be mixed in the same game.

### Persistence

**coherence** supports [persistence](broken://pages/-MYgPvUyuL6aH8ZrwmnB) out of the bo&#x78;**.** This means that the state of the world is preserved no matter if clients or simulators are connected to it or not. This way, you can create shared worlds where visitors have a lasting impact.

### Engine support

{% hint style="info" %}
**The coherence SDK** only supports **Unity** at the moment. **Unreal Engine** support is planned. For more specific details, please check the [Unreal Engine Support](/2.3/support/unreal-engine-support) page. For custom engine integration,[ please contact our developer relations team](mailto:devrel@coherence.io).
{% endhint %}

## General features

* Custom UDP transport layer using bit streams with reliability
* WebRTC support for WebGL builds
* Smooth state replication
* Server-side, Client-side, distributed authority
* Connected entity support
* Fast authority transfer
* Remote messaging (RPC)
* Persistence
* Verified support for Windows, macOS, Linux, Android, iOS and WebGL
* Support for Rooms and Worlds
* Floating Origin for extremely large virtual Worlds
* TCP Fallback
* Support for Client hosting through Steam Datagram Relay

### Unity SDK

* Unity SDK with an intuitive no-code layer
* Per-field adjustable interpolation and extrapolation
* Input queues
* Easy deployment into the cloud
* Multi-room Simulators
* Multiple code generation strategies (Assets/Baking, automated with C# Source Generators)
* Extendable object spawning strategies (Resources, Direct References, Addressables) or implement your own

### Optimization and performance

* Per-field compression and quantization
* Per-field sampling frequency adjustable at runtime
* Unlimited per-field levels of detail
* Areas of interest
* Accurate Simulation Frame tracking
* Network profiler

### Hosting and services

* Online Dashboard for management and usage statistics
* Automatic server deployment and scaling
* Multiple regions in the US, Europe and Asia
* Player accounts with a persistent key/value store
* Matchmaking and lobby rooms

{% hint style="info" %}
If you need to support your game in mainland China, please contact us for a custom solution.
{% endhint %}


# Why choose coherence?

And why coherence makes it feasible

Our main goal is to make multiplayer **accessible** for teams and individuals that wouldn't consider it otherwise because multiplayer is scary, expensive, requires dedicated expertise and overall is a risk you cannot take.

We know how it feels, because we're a bunch of gamedevs that have been there before.

This article explores what we bring to the table.

### Porting to multiplayer at any stage — including post-release

It is generally believed that converting an existing single-player game to multiplayer is next to impossible. We've proven this wrong time and time again. We've ported projects, small and big, from proof-of-concept within days, to finished full-blown multiplayer within a few months.

The following features help understand why it can happen when leveraging **coherence**.

### Composition, not inheritance

coherence networks GameObjects by adding a [CoherenceSync](/2.3/manual/components/coherence-sync) component — as simple as that. There is no need to derive your scripts from any base class, which is especially painful when your architecture already relies on your objects deriving from a base class of your choice.

<figure><img src="/files/g2MDrNFwzDAtx3DBVTYC" alt="" width="398"><figcaption></figcaption></figure>

### Sync what you already have

No `NetVars`, no custom serialization code. [Syncing variables](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing) is super easy. No code involved—choose what you want to sync, and you're good to go.

<figure><img src="/files/SlvoJeNHb9vIElthNkJ3" alt="" width="397"><figcaption></figcaption></figure>

This makes the transition to multiplayer smooth and quick, as you don't have to rewrite the networked components nor other parts of the codebase which rely on those variables.

### Instantiate and destroy as you usually would

No special calls like `netManager.Instantiate()` or `netManager.Destroy()` needed. We handle all the networking bits of the [object lifetime](/2.3/manual/networking-state-changes/instantiate-and-destroy-objects) behind the scenes so that you can focus on the fun stuff.

<figure><img src="/files/fKYEwj4aZYblP1bpRPT8" alt="" width="563"><figcaption></figcaption></figure>

### Use your prefabs in single-player and multiplayer

Due to our flexible [Component Actions](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing#component-actions) system, you can choose what should happen when a given component is used in multiplayer. This makes it trivial to reuse the same Prefab in both single-player and multiplayer modes. Got a PlayerController, which should be enabled only for your player and not remote ones? Easy-peasy. Need a RigidBody to be kinematic on the remote player? One click away.

<figure><img src="/files/dTtYr7zehnUC9hIr2hva" alt="" width="397"><figcaption></figcaption></figure>

### RPCs without branching

Whether online or offline, sending a [command](/2.3/manual/networking-state-changes/commands) will have the same effect. Due to our Authority system, this works even if the command would normally be received by another Client—in single-player, you have the [authority](/2.3/manual/networking-state-changes/authority) over all entities, and so the function will still be called. Neat!

```csharp
CoherenceSync sync;

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        // Works both in single-player and multiplayer
        sync.SendCommand(SpawnFireworks, MessageTarget.All, transform.position);
    }
}

public void SpawnFireworks(Vector3 position)
{
    Instantiate(FireworkPrefab, position, Quaternion.identity);
}
```

### Effortless bandwidth optimization

Even if porting initially goes smoothly, you might soon discover that the game feels extremely laggy. This fabulous horde of zombies is using too much bandwidth; yikes! You're left with a choice - redesign the game to be less cool or spend precious hours on handcrafting bandwidth optimizations for your networked objects.

We give you a third choice—keep the game cool and [optimize](/2.3/manual/optimization/level-of-detail-lod) within minutes. Trim your floats, limit your ints, remove whole components for objects at a distance—all with just a few clicks in our network LODing system. You are in control of every single bit!

<figure><img src="/files/sUcCRiWvqjy0DuVo5QWU" alt=""><figcaption></figcaption></figure>

### Hierarchy and physics that *just work*

[Hierarchy](/2.3/manual/networking-state-changes/child-gameobjects) and [physics](/2.3/manual/networking-state-changes/rigid-bodies) are among the hardest elements to sync. We made sure you can be unbothered by them by making them work out-of-the-box.&#x20;

<figure><img src="/files/nNzUGuzG9bN4EgflYK0E" alt="" width="563"><figcaption></figcaption></figure>

### Built-in interpolation

Even with the best netcode in the world, interpolation is what makes the difference between a smooth multiplayer experience and a choppy, rubber-banding slide show. We prefer the former, and thus, we provide you with a solid, yet flexible, state-of-the-art interpolation system.

While position, rotation, and scale are interpolated by default, you can enable interpolation for any synced variable with just one click. Choose between different forms of interpolation, tweak settings, or provide your own.

<figure><img src="/files/qJgEgxqt17CzdmDKts0c" alt="" width="535"><figcaption></figcaption></figure>

### Quick iterations

Testing multiplayer can be extremely time-consuming, especially if it requires building a game client. Being mindful of this, we've made coherence compatible with [ParrelSync](/2.3/getting-started/setup-a-project/local-development/local-testing-via-parrelsync) and [Multiplayer Play Mode](/2.3/getting-started/setup-a-project/local-development/multiplayer-play-mode)  out-of-the-box. These two solutions let you run multiple editor instances of your project, so you can skip the build process.

It's also possible to [run multiple clients from within the same Unity editor](/2.3/manual/multiple-connections-within-a-game-instance), for an extremely fast prototyping worflow.

<figure><img src="/files/dlkLYaqbVseRh2g2rijF" alt="" width="563"><figcaption></figcaption></figure>

### Flexible topology

Games have different networking needs. Coop games are usually played with friends and rarely need cheat prevention. Some games require cross-play, and others need persistent, cheat-proof worlds hosted on game servers.

coherence doesn't force you into a single networking topology. We don't follow the traditional client-server formula. Due to our flexible authority system, you can adjust topology at any stage of development rather easily.

Why overspend on dedicated servers early on if you can start with [peer-to-peer](/2.3/hosting/client-hosting) at no infrastructure cost, test the waters, and move to a more secure option at any point?

{% embed url="<https://www.youtube.com/watch?v=EpIlyg164w8>" %}

### An infrastructure built for coherence

Alongside all the tools you get for Unity development, you can opt-in to use coherence Cloud. We offer a very generous free tier with no compromise.

coherence Cloud is tightly integrated within the editor tools, and grants you quick and cost-effective access to a backend infrastructure to host your game on, allowing for **cross-play**, easy scaling, and services such as [player accounts](/2.3/hosting/coherence-cloud/authentication-service-player-accounts), [lobbies](/2.3/hosting/coherence-cloud/game-services/lobbies) or [data storage](/2.3/hosting/coherence-cloud/game-services/cloud-storage).

This platform is also very useful in development stages, to get prototypes and ideas going among teams, and to organize playtest sessions with external users. We offer a game portal that hosts game builds to players — both web (playable from within the portal) and desktop builds (downloadable) gives zero-hassle access to your games, in a minutes-away deployment process.

### Give it a shot!

You're now ready to tackle your first try at networking your game with coherence. We have all the tutorials and resources you need, as [videos](/2.3/getting-started/video-tutorials) or interactive [step-by-step demos](/2.3/getting-started/samples-and-tutorials), whichever you prefer. Good luck!


# Beginner's guide to networking

This article is an exploration of how networked games work. It does not cover code examples and doesn't delve into details. Instead, the goal is to prepare someone new to multiplayer programming to think about networking from a high-level perspective; what problems can arise and how they are commonly solved.

This knowledge, while useful to understand coherence, is general enough to be applicable to any other similar game networking solution.

***

When a game runs on your computer, it contains data that models the game. This includes things like the position of the players, the physical forces applied, and any gameplay-specific variables. We refer to this data as **state**. Updating state efficiently is a hard problem, even for a game that is completely offline.

To create the illusion that you're playing together in the same game space, a multiplayer game has to transmit enough of its state to the other players. Since computer networks have limited bandwidth, it is necessary to restrict the amount of data being sent. It's not feasible to send everything, all the time — there's compromises to make.

In the world of game networking, we commonly apply two strategies; we can send the state directly, or we can send inputs, and let the game apply them, updating state indirectly. These strategies are not exclusive, a game can use both mechanisms to keep the illusion of a realtime virtual space.

#### Sending State

In this approach we send enough data to replicate on other clients what we see locally.

For every player on the network, game state might evolve in different ways. For example, different players will produce different inputs, experience different latency or their computers might not be able to consistently simulate the game at constant speed.

By sending state directly, the forementioned game state divergence is continuosly adjusted, as long as they have a chance to catch up. This concept is usually referred to as [eventual consistency](https://en.wikipedia.org/wiki/Eventual_consistency), as it's coherence's model when sending state.

Since we're sending state constantly, we don't depend on an initial state, allowing features like late joining, or backing up the state at any given time.

When the game clients run the simulation locally and then send state to other players, we say it's **client-authoritative**.

This strategy can be costly if there's a lot of state to manage, like a huge number of entities being created, destroyed or updated. While it's possible to compress and reduce the amount of state sent, some games might benefit from a different approach — sending inputs instead of state.

#### Sending Inputs

From a game design perspective, it is usually possible to enumerate the player's allowed inputs (e.g. jump, run, activate).

When an input is processed, we can inform every other player in the session. If we make sure that each player starts the game in exactly the same state, and make sure that everyone applies exactly the same inputs as everyone else, the game state will appear in sync for each player. For games with that hold a lot of state, but offer a contained number of inputs, it can be an efficient networking strategy.

A good example are real-time strategy games. RTS games usually handle with hundreds of units. It might be enough to send the coordinates of mouse clicks instead of the location of each unit. This however requires completely **deterministic** game logic, which is a challenge in itself.

Another problem is that if there's even the slightest mismatch in inputs, the local game states of the players will begin to diverge. To learn more about this approach (and how to work around some of the problems) see our documentation on rollback networking.

{% content-ref url="/pages/-MhE2qWTumGbt2hz9pUk" %}
[Determinism, prediction and rollback](/2.3/manual/advanced-topics/competitive-games/determinism-prediction-rollback)
{% endcontent-ref %}

#### Calling methods remotely

Aside from pure state, we might want other players to execute specific methods. For example, instead of just setting a `Game Finished` flag to `true` when the game ends, we might want to let everyone know the game has finished by calling an `EndGame()` method that handles this logic directly. In many network solutions this is referred to as RPCs. In coherence, we call these commands.

A command or an RPC is a method tagged to be invoked on other game clients in the network.

{% content-ref url="/pages/-MYOiEBG8dSTN8aRpkUY" %}
[Commands: invoking methods](/2.3/manual/networking-state-changes/commands)
{% endcontent-ref %}

#### Holding State in a Single Source of Truth — The Simulator

Sending state and sending input are not exclusive, games can benefit from these two strategies.

Some games require state to not be transmitted by players, but by a special game client hosted somewhere online. This is usually the case for games with competitive nature, where preventing cheating is a major concern.

In game networking this is often referred to as dedicated servers. In coherence we refer to it as **simulators**.

In a game where there's a simulator involved, clients send inputs and receive state. The simulator takes those inputs and applies them, simulating the state for the rest of the players. This is caled **server-authoritative**.

This has multiple implications, for example it shifts some of the burden of computation from user devices onto the server. To read more about this approach, see our section on server-authoritate setup.

{% content-ref url="/pages/-MYg2ISb335jll59Sw6A" %}
[Server-authoritative setup](/2.3/manual/networking-state-changes/authority/server-authoritative-setup)
{% endcontent-ref %}

{% hint style="success" %}
With coherence you can combine server-authority and client-authority in interesting and useful ways. For example, it is possible to let players simulate some less-critical parts of the game state locally, while still sending player inputs to a simulator.
{% endhint %}

### Optimizations

By keeping track of what the other players know about the state of your game, it is often possible to reduce costly state transfer. For example, a player might drop an item on the ground, and send the new location of it to each other participant. Unless that item moves, it is unnecessary to keep sending the same position over and over. This simple idea is used pervasively in **coherence** (and other similar networking solutions) to great effect.

It's important to acknowledge that a game sometimes generates many changes in a short timeframe. In such a situation, it is useful to prioritize changes based on how important they are for the particular game in question, while also factoring in how long it has been on hold. This means that an "old" change that doesn't get sent will build up importance and relative priority compared to other changes, eventually getting sent.

Finally, a major way of limiting state transfer is to filter out uninteresting information and only send the most important parts based on the needs of each player.

There's two mechanisms involved in limiting or filtering game state; what each entity decides to send and what players wants to receive. These two perspectives shape Levels of Detail (LODs) and Queries respectively.

{% content-ref url="/pages/LAVhCmK6dnWiEgouwUMn" %}
[Level of detail (LOD)](/2.3/manual/optimization/level-of-detail-lod)
{% endcontent-ref %}

{% content-ref url="/pages/EJboKWR9cXenHZ0yGj07" %}
[Queries](/2.3/manual/optimization/areas-of-interest)
{% endcontent-ref %}

### Relay

We've covered sending inputs and sending state. But we didn't cover what that really means. Some networking solutions require explicit client-server architectures, where communications are direct and clear; clients send to the server, the server responds back.

In coherence, **it doesn't work that way**. Even when using simulators, all the data is routed through a smart relay, at the core of our tech stack — the Replication Server.

The role of the Replication Server is to keep track of who is connected and routes inputs and state back and forth between all connected clients and simulators. The Replication Server has knowledge of the game entities that can exist in the world, and applies queries and LODs to filter game state efficiently.

Having the concept of a smart relay deattached from who holds state allows for a truly flexible and modular approach to networking that's core to how we solve networking. At the core of this flexibility, there's **authority**, or who dictates state over a network entity.

### Authority

In any network transaction, there's always someone sending, and someone receiving. It's a one-to-many relationship. When an entity is sending state, we call it the **authority**. We can also refer to this as *the owner of the entity*, given the authority dictates the simulation.

In coherence, authority is not per client but **per entity**, and it breaks down into State Authority and Input Authority — an entity might be the Input Authority (simulates the inputs) but not the State Authority (someone else is in charge of the state).

Authority can be both **transferred** and **requested**. This allows for adjust your topology on the go. For example, you might decide that items near your player, or that the player picks up, are simulated by the player. Or you might decide who should be in charge of the global state (on a peer-to-peer) based on latency, and request/transfer authority accordingly.

{% content-ref url="/pages/-MYPXxjUQ4ebxbnhK4Cs" %}
[Authority transfer](/2.3/manual/networking-state-changes/authority/authority-transfer)
{% endcontent-ref %}

### Transport Layer and Reliability

At the core of networking there's a layer called the Transport Layer. In this layer, there's two protocols used.

On one side there's TCP. TCP is reliable, meaning packets are given numbers and read in order. When a packet is lost, it's requested again. There's checksums and other mechanisms to ensure that the information you receive is exactly the information sent.

This transport does not work well for fast-paced games, since their simulations run at many frames per second. By the time a lost network message has been resent and finally made it to its final address, the information in it will have a high chance of already being outdated.

On the other side there's UDP. UDP is not reliable, meaning packets are sent, but there's no guarantees of their order, or if they are lost.

**coherence** however adds a smart reliability layer on top of this protocol. If a packet didn't make it to its recipient, that packet will be sent again, but only after checking if any more recent changes to its data exist. This way, it is more likely that each player gets a consistent and up-to-date view of the shared game state.

### Time and Latency

Sending data from one computer to another takes time, and there's no way around that. As a developer, it is important to embrace this fact and recognize that **it changes how you must think about your game logic**. When programming a single-player game (especially if it only runs on a single processor thread) we can assume that any change to the game state is immediate. In a networked game, this is not true.

This means that each player of a networked game is playing in their own "parallel universe", which affects each other at a distance. Updates to data that you don't have authority over will appear in an irregular and unpredictable way. Knowing that fact, the challenge becomes how to correct out-of-order updates, unnatural movement and other unexpected circumstances.

One way to mask and smooth this reality is interpolation. Interpolation is able to take snapshots of the state and blend them in a more natural and precticable way. coherence has interpolation built-in on its core, and all state you receive can be interpolated at the click of a button.

{% content-ref url="/pages/-MYgThhR2VM1MFY3PMQ6" %}
[Interpolation](/2.3/manual/networking-state-changes/interpolation)
{% endcontent-ref %}

### Conclusions

We hope that you feel more confident now thinking about the challenges of networked games. While networking surely can be tricky at times, it's also immensely cool and fun when it works. We believe **coherence** will make you reach that point in no time!

Now that you grasp what this is all about, we can get hands dirty.


# Installation

{% hint style="info" %}
If you are looking to update, check out the [upgrade guide](/2.3/support/upgrading-unity-sdk) and the [release notes](/2.3/support/release-notes).
{% endhint %}

<details>

<summary>Supported <i class="fa-unity">:unity:</i> Unity versions</summary>

<table><thead><tr><th width="187.60546875">Unity Release Stream</th><th width="198.4921875">Unity Minimum Version</th><th>Remarks</th></tr></thead><tbody><tr><td>6.4</td><td>6000.4.0f1</td><td></td></tr><tr><td>6.3 LTS</td><td>6000.3.0f1</td><td></td></tr><tr><td>6.0 LTS</td><td>6000.1.17f1</td><td></td></tr><tr><td>2022 LTS</td><td>2022.2.5f1</td><td></td></tr><tr><td>2021</td><td>2021.3.45f2</td><td>Legacy — works but not actively supported anymore.</td></tr></tbody></table>

{% hint style="info" %}
We follow Unity's release cycles closely to support `Recommeded` versions of the Unity Editor. If you experience issues working with these versions, please [reach out to us](/2.3#join-the-community).

Additionally, we support newer versions as soon as we can. If you're on a bleeding-edge Unity version and are experiencing issues, get in touch with us.
{% endhint %}

</details>

<details>

<summary>Option 1 — Scoped Registry via Unity Editor</summary>

In your Unity project, go to **Edit** > **Project Settings**. Under [Package Manager](https://docs.unity3d.com/Manual/class-PackageManager.html), add a new Scoped Registry with the following information:

* Name: `coherence`
* URL: `https://registry.npmjs.org`
* Scope(s): `io.coherence.sdk`

<figure><img src="/files/zUyUZYcDRtyFFq5mCu1O" alt=""><figcaption></figcaption></figure>

The Scoped Registry is added. Next, let's tell Unity to install coherence from it.

Open the [Package Manager Window](https://docs.unity3d.com/Manual/upm-ui.html) via **Window** > **Package Management > Package Manager** or the icon in Unity's Main Toolbar.

<figure><img src="/files/rTs4YU0p4boGjMO57sfj" alt=""><figcaption></figcaption></figure>

coherence is available through the **My Registries** section.

<figure><img src="/files/aiiOaZ8SJc0NH8Fzhgy5" alt=""><figcaption></figcaption></figure>

Select the coherence registry in the left panel, then the coherence package in the main panel, and click **Install** in the right panel.

</details>

<details>

<summary>Option 2 — Scoped Registry via <code>manifest.json</code></summary>

{% hint style="info" %}
Refer to Unity's instructions on [adding a Scoped Registry](https://docs.unity3d.com/Manual/upm-scoped-use.html) for more in-depth documentation.
{% endhint %}

Edit `<unity-project>/Packages/manifest.json` with the additions highlighted below:

<pre class="language-json"><code class="lang-json">{
  "dependencies": {
<strong>    "io.coherence.sdk": "2.2.0",
</strong>    "com.unity.ugui": "1.0.0",
    "com.unity.modules.imgui": "1.0.0",
    /* ... */
  },
<strong>  "scopedRegistries": [
</strong><strong>    {
</strong><strong>      "name": "coherence",
</strong><strong>      "url": "https://registry.npmjs.org",
</strong><strong>      "scopes": [
</strong><strong>        "io.coherence.sdk"
</strong><strong>      ]
</strong><strong>    }
</strong><strong>  ]
</strong>}
</code></pre>

Once Unity is focused, this file is reloaded and installation begins.

</details>

<details>

<summary>Option 3 — Asset Store</summary>

[![Download on the Asset Store](https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVdg1mQWQDUz5SLS0S3i2%2Fuploads%2FSN3kaiMlI76jB5QYqIs1%2Fimage.png?alt=media\&token=fd8b5088-26e6-4e88-9945-f76219ecba6b)](https://u3d.as/3q1m)

{% hint style="warning" %}
When installing through Asset Store, coherence is installed via **.unitypackage** and installs the package in `Packages/io.coherence.sdk`, becoming **embedded** (see [Unity's Documentation on Package Sources](https://docs.unity3d.com/Manual/upm-concepts.html)). This makes upgrading fragile, since files being renamed or moved will definitely break compilation and introduce unexpected issues. Refer to the [Upgrade Guide](/2.3/support/upgrading-unity-sdk) if you decide to use the Asset Store version.
{% endhint %}

</details>

***

{% hint style="success" %}
When you successfully install coherence, you should be welcomed with the **coherence Hub**.
{% endhint %}

<figure><img src="/files/drqQa47ZF3iASt8vDB1W" alt=""><figcaption></figcaption></figure>


# Setup a project

Once [coherence is installed](/2.3/getting-started/installation), we can start networking.

{% hint style="info" %}
We recommend for first-time users of coherence to go through this flow in an empty project **at least once**, before trying to network an existing game. This will give you a good understanding of the different aspects that make up the coherence toolset.
{% endhint %}

We'll cover how to:

* [Prepare a Unity scene](/2.3/getting-started/setup-a-project/scene-setup) for network synchronization. This requires a [CoherenceBridge](/2.3/manual/components/coherence-bridge), at least one [CoherenceLiveQuery](/2.3/manual/components/coherence-live-query), and an in-game UI for connecting (see: [Sample UIs](/2.3/getting-started/samples-and-tutorials/samples-connection-uis)).
* [Configure Prefabs](/2.3/getting-started/setup-a-project/prefab-setup) to sync over the network using the [CoherenceSync](/2.3/manual/components/coherence-sync) component.
* Test your game [locally](/2.3/getting-started/setup-a-project/local-development).
* [Try the game live](/2.3/getting-started/setup-a-project/test-in-the-cloud) with coherence Cloud.

In the sub-pages of this section we'll go through all of them. [**Let's begin!**](/2.3/getting-started/setup-a-project/scene-setup)


# 1. Scene setup

{% hint style="info" %}
If you prefer a video tutorial, refer to the first minute of [Part 2](https://youtu.be/kyUSiBpZ2Bc) of our Getting Started series.
{% endhint %}

One of the first steps in adding coherence to a project is to setup the scene that you want the networking to happen in.

### **Add a CoherenceBridge**

In the top menu: *GameObject > coherence > Bridge*

A GameObject with a `CoherenceBridge` component will be created in the scene, that we will refer to as CoherenceBridge or *the bridge*.

CoherenceBridge manages the connection with coherence's relay (i.e., the [Replication Server](/2.3/manual/replication-server)) and is the centre of many connection-related events.

No particular setup is required now, but feel free to explore the options in its Inspector.

### **Add a CoherenceLiveQuery**

In the top menu: GameObject *> coherence > Live Query*

A GameObject with a `CoherenceLiveQuery` component will be created in the scene, that we will refer to as CoherenceLiveQuery or *the live query*.

A [CoherenceLiveQuery](/2.3/manual/components/coherence-live-query) defines what part of the world the Client is interested in when requesting data from the Replication Server. When **Constrained**, it covers limited volume. The **Extent** property specifies how far it reaches. Anything that is **outside** the area defined by the LiveQuery **will not be synced**.

For a big game world, it makes sense to use a small range and parent the LiveQuery to the player character or the camera, so it can move with it. But for now, let's just position it at the centre of the world (unparented), and keep it as **Infinite** (no spatial constraints).

<figure><img src="/files/XV7gFp7pRrT9EnpCcCjy" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
While LiveQueries are an optimisation tool, having at least one LiveQuery is **necessary**.
{% endhint %}

### **Add** a Connect Dialog

We'll be using coherence's Sample UI since it has everything we need to get kickstarted.

In the top menu: *coherence > Hub*

Within the Hub, go to the Samples tab. Within UIs you will find the Rooms Sample UI

<figure><img src="/files/tqJvBE1ODm6EmYplffbr" alt=""><figcaption></figcaption></figure>

The imported sample has a demo scene, but what matters to us now is the `Room Connection Dialog.prefab`, which we can drop on our scene.

{% hint style="info" %}
This sample uses Unity GUI (UGUI). For input events to be forwarded properly, you'll need at least an EventSystem (GameObject > UI > Event System)
{% endhint %}

A Connect dialog UI provides an interface for the player to connect to the Replication Server, once the game is running. You can create your own connection dialog, but we provide a few examples as a quick way to get started and for prototyping. Read more in the section dedicated to [Sample UIs](/2.3/getting-started/samples-and-tutorials/samples-connection-uis).

This is how your scene should look like

<figure><img src="/files/vANPvjhKsu9CsUn9Bz4C" alt=""><figcaption></figcaption></figure>

***

{% hint style="success" %}
**In this section, we:**

* Added a [CoherenceBridge](/2.3/manual/components/coherence-bridge) to the scene to facilitate connection to the [Replication Server](/2.3/manual/replication-server)
* Used a [CoherenceLiveQuery](/2.3/manual/components/coherence-live-query) to ensure we receive network updates
* Added an in-game UI to allow players to connect over the network

Next: time to [setup some Prefabs](/2.3/getting-started/setup-a-project/prefab-setup)!
{% endhint %}


# 2. Prefab setup

Preparing GameObjects and Prefabs for network replication

{% hint style="info" %}
If you prefer a video tutorial, refer to [Part 2](https://youtu.be/kyUSiBpZ2Bc?t=63) of our Getting Started series.
{% endhint %}

To start networking a Prefab, simply select a Prefab or GameObject you wish to network, and on the Inspector window, click **Sync with coherence**. In this case, we've created a basic cube.

<figure><img src="/files/LMAByF3fcfrEhVpgOTTe" alt=""><figcaption></figcaption></figure>

This adds a CoherenceSync component to that Prefab, which is all it takes to acknowledge it in the network.

{% hint style="success" %}
Any Prefab that has the CoherenceSync component on it is known as a Networked Prefab. You can inspect which Networked Prefabs you have currently in your project via top menu `coherence > Networked Prefabs`.
{% endhint %}

Next, we want to select which variables to network.

Open the Configure window, accessible from within the CoherenceSync Inspector.

<figure><img src="/files/NEQCHuzkfcB4rg8WfONi" alt=""><figcaption></figcaption></figure>

From within the Configure window, you can toggle the variables you care about being networked.

You can toggle any variable available in this window, including custom scripts attached to the GameObject and any of its children. To network variables on children, refer to [Syncing child GameObjects](/2.3/manual/networking-state-changes/child-gameobjects).

Let's toggle `rotation` and `localScale` in the `Transform` component, so that we network all three properties.

If you move into the `Methods` tab, you can toggle methods to create [Network Commands](/2.3/manual/networking-state-changes/commands).

For now we're not going to be using commands, so we can leave this window untouched.

Next up is the `Components` tab. On this windows you decide how your components should behave, based on [authority](/2.3/manual/networking-state-changes/authority) — this is useful to quickly turn logic on/off depending on who is simulating the GameObject currently.

{% hint style="info" %}
The Components tab of the Configure window offers a quick way to react to network state changes. However, for advanced scenarios where you want to have full control over what happens, you hook into the numerous UnityEvents that CoherenceSync exposes, both through UI or through code.
{% endhint %}

Let's make our cube change color based on who owns it. To do so, we select `Handle Material` in the `Mesh Renderer` component.

<figure><img src="/files/vUDpCXTzu3ZUEv9atUuC" alt=""><figcaption></figcaption></figure>

Now, let's create two materials. We'll use green for authority and red for remote.

<figure><img src="/files/mKhMoOmywAwOo7jZN8AQ" alt=""><figcaption><p>New Authority.mat material, using a bright green color</p></figcaption></figure>

<figure><img src="/files/g3Qkzpz8AfEIKqfJVQVy" alt=""><figcaption><p>Reference the materials</p></figcaption></figure>

### Commiting the changes

When Networked Prefabs are added or removed, or the variables to network within them change, you will need to **bake** to commit the changes. coherence informs you about the need to bake in different ways (check out [Baking](/2.3/manual/baking-and-code-generation) section), but for the time being, let's focus on one of them — the bake button on the Project Window:

<figure><img src="/files/D6EOsJhiHqFhOg2BlsPD" alt=""><figcaption><p>The Project Window warns when baking is required.</p></figcaption></figure>

That warning icon tells you there's changes made on Networked Prefabs that require to bake. Simply click the button to perform a bake operation.

From now on, every change we do and want to commit to, we'll need to bake i.e., press this button.

{% hint style="success" %}
Refer to [Baking](/2.3/manual/baking-and-code-generation) for an in-depth exploration of what baking does and why it's essential.
{% endhint %}

### What we have so far

At this point, we have:

* A blank scene (with default Camera and Directional Light)
* To that scene, we've added a CoherenceBridge, a CoherenceLiveQuery and a Connection Dialog Prefab that will handle the connection logic
* A Cube that we converted into a Networked Prefab.
  * We're syncing Transform's position, rotation and scale.
  * We're changing Mesh Renderer material based on authority.
* Baked!

We're now ready to test what we have. **No, so far we've written no logic**. Next, we'll be using the Unity Editor in Play Mode to illustrate how networking happens.

***

{% hint style="success" %}
**To recap**

This is it! Setting up an object to be networked doesn't require additional steps:

* A Prefab with a `CoherenceSync` on it
* Configuring what to sync in the **Configure** window
* Baking

Now let's run this setup [**locally**](/2.3/getting-started/setup-a-project/local-development) or using the [**coherence cloud**](/2.3/hosting/coherence-cloud).
{% endhint %}


# 3. Playing locally

{% hint style="info" %}
If you prefer a video tutorial, refer to [Part 2](https://youtu.be/kyUSiBpZ2Bc?t=165) of our Getting Started series.
{% endhint %}

We need at least two clients connected, and a Replication Server to connect them to.

## Run a local Replication Server

You can run a local Replication Server directly on your machine by either:

* Launch the Replication Server from the menu

<figure><img src="/files/4izQYVoQMYitFS2frNNb" alt=""><figcaption></figcaption></figure>

* Or through the **Hub**

<figure><img src="/files/Jl3kZ7F7LPH21oOct5Ih" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Whether you run a Replication Server for Rooms or for Worlds depends on [which setup you plan to use](/2.3/manual/replication-server/rooms-and-worlds), which in turn requires the correct corresponding [Sample UI](/2.3/getting-started/samples-and-tutorials/samples-connection-uis).
{% endhint %}

Regardless of how you launch it, a new terminal window will open and display the running Replication Server:

<figure><img src="/files/zfsnbxzj2Z3xRGgjHFwV" alt=""><figcaption><p>The Replication Server running in the Terminal</p></figcaption></figure>

If the console opens correctly and you don't see an error line (they show up <mark style="color:red;">in red</mark>), it means your Replication Server is running! Now you should be able to connect to it, in the game.

## Run multiple instances of the game

It is often useful to be able to run multiple instances of your game on the same device. This allows you to simulate multiple player connections.

There are multiple ways to do this:

* [Make a build](/2.3/getting-started/setup-a-project/local-development/local-testing-using-builds) of the game
* Use [ParrelSync](/2.3/getting-started/setup-a-project/local-development/local-testing-via-parrelsync) to create clones of the project
* Use the [Multiplayer Play Mode](/2.3/getting-started/setup-a-project/local-development/multiplayer-play-mode) package

Dive into the individual pages to see our recommendation for each option.

{% hint style="info" %}
In this example, we will be connecting **one client always with the editor**, and the other one will be a standalone desktop build.
{% endhint %}

### Enter Play Mode

To test this setup, enter Play Mode on the Unity Editor, and use the rendered Sample UI to connect to a room or a world. Once there, you will see nothing. The game is empty — we didn't add anything at edit time, so that makes sense.

Now, open a second client connection — open the game build, and connect to the same world or room that you're connected on via the Unity Editor. The game is equally empty.

<figure><img src="/files/sTLKY5epcXNKoKjpAQ8y" alt=""><figcaption></figcaption></figure>

Now both clients are connected. Let's network while the game is open!

In the Unity Editor, find your Networked Prefab (our Cube, as described in the previous sections) and drag it on the scene.

<figure><img src="/files/S8Zff60Foe2XEmH7qmeZ" alt=""><figcaption></figcaption></figure>

The Unity Editor will show the Cube as green, since the editor is the one creating it (hence, has State Authority over it).

The build will show the Cube as red, since it's a replicated entity (doesn't have State Authority).

We can modify the transform in whatever way we want on the editor, and the changes will be replicated on the build.

***

{% hint style="success" %}
**In this section, we:**

* Ran a local Replication Server
* Saw how to run multiple instances of the game
* Connected to the Replication Server

Now that we know things work locally, it's time to [test the game in the coherence Cloud](/2.3/getting-started/setup-a-project/test-in-the-cloud)!
{% endhint %}


# Builds

An easy way to test your game locally is to simply create a build, and open several instances of it.

You can also connect the Editor alongside the builds, with the extra benefit of being able to inspect the hierarchy and the state of its GameObjects.

**Pros**

* Easy to distribute amongst team members and testers
* Well-understood workflow
* Can test with device-specific constraints (smartphones, consoles, ...)

**Cons**

* Not the shortest iteration time, as you need to continuously make builds
* Harder to debug on the builds (requires custom tooling on your side to do so)

Read [Unity's documentation on how to make a game build](https://docs.unity3d.com/Manual/BuildSettings.html).

{% hint style="success" %}
Make sure you've read through Local Development and have started a [Local Replication Server](/2.3/getting-started/setup-a-project/local-development).
{% endhint %}

## Requirements

Go to [Project Settings > Player](https://docs.unity3d.com/Manual/class-PlayerSettings.html) and:

* Enable **Run in Background**.
* Set [**Allow downloads over HTTP**](#user-content-fn-1)[^1] to **Always allowed**.
* Disable **Force Single Instance**.
* (Optional) Set **Fullscreen Mode** to **Windowed**
* (Optional) Enable **Resizable Window**.

## Testing Time

When the build is done, launch it. Enter Play Mode from within the Unity Editor.

Click *Connect* in the connection dialogs on both instances.

Now, try focusing on one and using WASD keys. You will see the box move on the other side as well.

[^1]: This is a new setting introduced in Unity 2022.\
    \
    coherence communicates with self-hosted Replication Servers through HTTP (which includes local development).


# ParrelSync

[ParrelSync](https://github.com/VeriorPies/ParrelSync) is an open-source project which allows you to open multiple Unity Editor instances, all pointing to the same Unity project (using Symbolic links).

**Pros**

* Short iteration times
* Easy to debug since every client is an Editor
* Works with Unity versions prior to Unity 6

**Cons**

* Can be more resource demanding than just running builds
* Each clone requires the whole project to be duplicated on disk (1 clone means 2x the disk space, and so on). This might be a lot for huge projects.

## How to use?

* Install [ParrelSync](https://github.com/VeriorPies/ParrelSync) as described in their [Installation Instructions](https://github.com/VeriorPies/ParrelSync#installation)
  * UPM Package installation is preferred as coherence supports it out-of-the-box
  * If installed via .unitypackage, you need to set [`CloneMode.Enabled`](https://unityapi.coherence.io/docs/v2.2.0/api/Coherence.Editor.CloneMode.html#Coherence_Editor_CloneMode_Enabled) by yourself. One way is by adding the following script to an *Editor* folder in your project:

```csharp
// Assets/Editor/CoherenceClone.cs
// This script is only needed if you're installing ParrelSync via .unitypackage

using Coherence.Editor;

[InitializeOnLoad]
internal class CoherenceClone
{
  static CoherenceClone()
  {
    CloneMode.Enabled = ParrelSync.ClonesManager.IsClone();
  }
}
```

* Open *ParrelSync* > *Clones Manager*. Create a new clone, and open it
* Continue development in the main Editor. Don't edit files in clone Editors
* Make sure [baked data](/2.3/manual/baking-and-code-generation) is up-to-date before starting to test, and that the Replication Server is running with the latest [schema](/2.3/manual/advanced-topics/schema-explained) generated
* Enter **Play Mode** in each Editor

coherence tells apart ParrelSync clones from the main Editor, so it's easier for you to not edit assets in clones by mistake.

<figure><img src="https://lh7-eu.googleusercontent.com/oPye1yDqQhrUTYgnrXZsFoNJ7GN69qLnaVDz17ZI5J30OZFE8PGoS__VW0bANCkhL610jJPNYmXRU5mRU0GpR33DjvTx5q0ljury62UCK56Dq76XVytEhgvEWoMSHTc2vO3R2rP2JhIugvRDP0JJFo_q1A=s2048" alt=""><figcaption><p>Inspecting a CoherenceSync on a clone</p></figcaption></figure>

<figure><img src="https://lh7-eu.googleusercontent.com/iB77lZ975kiQ3XlF3eJNCHkwaHj0nL67IRUC8LKQlMFQTufnFoHeaFmnxFeVShcSBFYbb5f4MJheQHuRqZArq5ZXT2YN1WUIfzLXlms3ErA5jM2VwKN1ONWJ7qXWFBq5cZ3cHevcdxd-5GMqvxig47zV1g=s2048" alt=""><figcaption><p>Main Editor and a clone Editor side by side</p></figcaption></figure>


# Unity's Multiplayer Play Mode

[Multiplayer Play Mode](https://docs-multiplayer.unity3d.com/mppm/current/about/) (MMPM) is Unity's official solution for local multiplayer testing, available from Unity 6.

**Pros**

* Short iteration times
* Tighter integration within the Editor, doesn't require multiple (standalone) Editors open

**Cons**

* Requires Unity 6+
* Can be more resource demanding than just running builds

## How to use?

* Install MPPM as described in their [Installation Instructions](https://docs-multiplayer.unity3d.com/mppm/current/install/)
* Open *Window* > *Multiplayer Play Mode*
* Enable up to 4 virtual Players
* Make sure that the [baked data](/2.3/manual/baking-and-code-generation) is up-to-date before starting to test, and that the Replication Server [is running](/2.3/getting-started/setup-a-project/test-in-the-cloud/deploy-replication-server) with the latest schema
* Enter **Play Mode**

**coherence** tells apart virtual Players from the main Editor, so it's easier for you to not edit assets in clones by mistake.

<figure><img src="https://lh7-eu.googleusercontent.com/oPye1yDqQhrUTYgnrXZsFoNJ7GN69qLnaVDz17ZI5J30OZFE8PGoS__VW0bANCkhL610jJPNYmXRU5mRU0GpR33DjvTx5q0ljury62UCK56Dq76XVytEhgvEWoMSHTc2vO3R2rP2JhIugvRDP0JJFo_q1A=s2048" alt=""><figcaption><p>Inspecting a CoherenceSync on a virtual Player</p></figcaption></figure>


# 4. Playing in coherence Cloud

{% hint style="info" %}
If you prefer a video tutorial, refer to [Part 3](https://youtu.be/ZYJQzji1Oek) of our Getting Started series.
{% endhint %}

Now that we have tested our project locally, we can upload it to coherence Cloud and share it with friends and colleagues. To be able to do that, we need to [create a free account](https://coherence.io/login) with coherence.

At this point, you can create a free account, which will grant you a number of credits that are more than sufficient to go through developing and testing your game in coherence Cloud.

Open the **coherence Hub**, and go to the **Cloud** tab.

After pressing **Signup / Login** you will be taken to the [login page](https://coherence.io/login). Authenticate with your credentials, and return to Unity.

![](/files/cOgHFD3CVo7Vhx0EU10L)

Then, select your organization and project.

<figure><img src="/files/BIxf0CybTeJA1mDYK8Ta" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
You can create or edit a project from within the [coherence Cloud Dashboard](https://coherence.io/dashboard).
{% endhint %}

Next up, we need to give coherence Cloud our game's schema, so that it can kickstart a Replication Server for our game.

***

{% hint style="success" %}
**To recap**

We created a coherence account and connected in the Unity, so now we can see our orgs and projects directly within the Editor and link to them.

As a next step in the sub-pages of this section we'll see how to [deploy a Replication Server](/2.3/getting-started/setup-a-project/test-in-the-cloud/deploy-replication-server) in the cloud, and how to [share builds](/2.3/getting-started/setup-a-project/test-in-the-cloud/share-builds).
{% endhint %}


# Upload the Schema

{% hint style="info" %}
If you prefer a video tutorial, refer to [Part 3](https://youtu.be/ZYJQzji1Oek) of our Getting Started series.
{% endhint %}

In the **coherence Hub** window, select the **Cloud** tab, and click on **Upload Schema to Cloud**.

The **Cloud Status** in the **Schemas** section should now be *In Sync*.

<figure><img src="/files/SDJozsats3OA4viimCbq" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
If the status does not say "*In Sync*", or if you encounter any other issues with the server interface, refer to the [troubleshooting](/2.3/support/known-issues) section.
{% endhint %}

Your project schema is now deployed with the correct version of the Replication Server already running in the cloud. You will be able to see this in your cloud dashboard status.

<figure><img src="/files/0DyVdCycmShf97I60Z78" alt=""><figcaption></figcaption></figure>

You can now build the game and send the build to friends or colleagues for testing.

If you used one of the Connection Dialog samples, once you play the game it will fetch all the regions available for your project. This depends on the project configuration (e.g., the regions that you have selected for your project in the Dashboard).

You will be able to play over the internet without worrying about firewalls and local network connections.


# Share Game Builds

coherence Cloud allows you to upload and share the builds of your games to your team, friends or adoring fans via an easy-access play link.

It supports standalone desktop (Windows, macOS and Linux) and also Web builds.

You can host and instantly play your multiplayer game and share it around the world.

{% hint style="success" %}
You can use the [First Steps](https://coherence.io/games/coherence/first-steps-tutorial) or [Campfire](https://coherence.io/games/coherence/campfire-tutorial) projects to follow along this section.
{% endhint %}

First, build your game as you normally would. Next, we'll upload it to **coherence Cloud**.

## Upload Game Build to Cloud

In **coherence Hub**, select the **Cloud** tab.

You can upload your build from the **Share build** section.

Select the platform, browse for the previously-created build, and click **Upload Game Build to Cloud**.

<figure><img src="/files/YYTvOgLtsSRfftRzbc9P" alt=""><figcaption></figcaption></figure>

Once uploaded, it becomes available in your Public Page.

## The Public Page

Every project hosted in coherence Cloud can have a Public Page. This hosted site can hold your standalone builds (Windows, macOS and Linux) and will render a Web view (if any).

![A Web build running in the Public Page](/files/l4BfCHJvs0lzL0ZbiFDG)

It is the most straightforward way to share your work easily to friends and colleagues, specially early on, when you are ready to playtest.

Enable Public Page on coherence Cloud via `<project> > Schemas and Builds > Configure`:

<figure><img src="/files/DGBWvICSYT3Vm8c9dCCp" alt=""><figcaption></figcaption></figure>

On the `Game Builds` tab you can manage which builds become available, and can also remove them.

{% hint style="warning" %}
macOS builds might need some extra work to be launched:

* Give execution permissions to the .app
* Remove from quarantine

```bash
chmod +x "<game.app>/Contents/MacOS/<executable_name>"
xattr -r -d com.apple.quarantine "<game.app>"
```

{% endhint %}

***

{% hint style="success" %}
That's it! You made and shared a multiplayer game, hosted in the cloud. Surely it's simple for now, but now that the technical aspects are out of the way, you can focus on fun gameplay.

We recommend heading to our Samples and Tutorials section, dive [into the samples](/2.3/getting-started/samples-and-tutorials/package-samples) or watch some [video tutorial](/2.3/getting-started/video-tutorials), to learn all about deeper topics.
{% endhint %}


# Samples and tutorials

coherence offers a variety of **Samples**, which you can access through the coherence Hub.

<figure><img src="/files/cylRj4K7qa6M3sEKvZFS" alt=""><figcaption></figcaption></figure>

<table data-view="cards" data-full-width="false"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Sample Scenes</td><td>Included in the SDK, perfect to start</td><td><a href="/files/Pw7KMDbXBhcBx9J2tZ6A">/files/Pw7KMDbXBhcBx9J2tZ6A</a></td><td><a href="/pages/vLtGxOrN3pexllDSRo5Y">/pages/vLtGxOrN3pexllDSRo5Y</a></td></tr><tr><td>First Steps</td><td>Individual scenes showing coherence features</td><td><a href="/files/mTtACXaSp0jGJLUNmz9o">/files/mTtACXaSp0jGJLUNmz9o</a></td><td><a href="/pages/WEETNIhtrltGwe15MqFo">/pages/WEETNIhtrltGwe15MqFo</a></td></tr><tr><td>Campfire</td><td>A project showing more advanced use of coherence</td><td><a href="/files/wWC0EhOLVFch0ytX6JJB">/files/wWC0EhOLVFch0ytX6JJB</a></td><td><a href="/pages/QSwDpmRrHCHCBYXHJExB">/pages/QSwDpmRrHCHCBYXHJExB</a></td></tr></tbody></table>


# Sample scenes

This sample cover a handful of coherence features in isolation. Here's what's covered:

* Character movement
* Distributed authority
* Physics
* Uniqueness and persistence
* Live queries
* Tag queries
* Player spawning

{% hint style="warning" %}
**When opening a scene, it shows up all magenta!**

If, once you import the samples, the scenes show up magenta/pink, it's because the samples are made for the built-in pipeline and your project is using either URP or HDRP.

To fix this in URP, go to: *Window > Rendering > Render Pipeline Converter*

Click on the checkboxes to choose what to convert (**Materials** is necessary), then click the **Initialize and Convert** button. After a brief loading, you should see the example scenes displayed correctly.

For more information, refer to Unity's guides [for URP](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@17.0/manual/features/rp-converter.html) or [for HDRP](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@17.0/manual/convert-from-built-in-convert-materials-and-shaders.html).
{% endhint %}


# Sample UIs

Sample UIs are ready-to-use interfaces that help players connect to a Replication Server running locally or in coherence Cloud.

The currently available samples are:

* [Rooms UI](#room-connect-dialog)
* [Worlds UI](#world-connect-dialog)
* [Lobbies UI](#lobbies-ui)
* [Matchmaking UI](#matchmaking-ui)

{% hint style="info" %}
The difference between Rooms and Worlds is explained on this page: [Rooms and Worlds](/2.3/manual/replication-server/rooms-and-worlds), while [Lobbies](/2.3/hosting/coherence-cloud/game-services/lobbies) have somewhat of a different role, in that they are usually used in addition to Rooms in a game flow.
{% endhint %}

## Importing a Sample UI

To import a sample UI into your project, open coherence via **coherence > Hub**, go the **Samples** page, select the sample you want under the **UIs** tab, and press **Import**.

<figure><img src="/files/n8zgb8Zw3Cw0MdWYjJCv" alt=""><figcaption></figcaption></figure>

This will cause the sample to get imported in the Samples directory of your project, if it isn't already.

![](/files/RfhEvXnmlkoXcoIetv5u)

## Rooms UI

The **Rooms UI** sample contains a dialog created using Unity UI that can be used to browse, create and join Rooms hosted in the coherence Cloud or in a locally hosted Replication Server.

### Setup

Before launching the sample scene, you need to either:

1. Start a [Replication Server](/2.3/manual/replication-server) running locally via **coherence > Run Replication Server for Rooms**,
2. or [log in to coherence Cloud](/2.3/getting-started/setup-a-project/test-in-the-cloud) via **coherence > Hub > Cloud > Signup / Login** and select a cloud Project to use.

You don't need to do anything else for the sample UI to work.

### Using the sample

The **Rooms Connect Dialog** has a few helpful components that are explained below.

<figure><img src="/files/lL3Kr8suD9wqEmgB6tNZ" alt="" width="375"><figcaption><p>The Rooms connection dialog</p></figcaption></figure>

* At the top of the dialog we have an **input field for the player's name**.
* Next is a **toggle between Cloud and Local**.\
  You can switch to Local if you want to connect to a Replication Server for Rooms that is running on your computer.
* Next is a **dropdown for region selection**. This dropdown is populated when regions are fetched from the coherence cloud. The default selection is the first available region.\
  This is not enabled when you switch from Cloud to Local. This is also only relevant if you deploy your game to several different regions.
* Next is a **dropdown of available Rooms** in the selected region (or in your local server if using the Local mode).
* After selecting a Room from the list the **Join** button can be used to join that Room.
* If you know someone has created a room but you don't see it, you can manually refresh the rooms list using the **Refresh** button.

#### Creating a room

The **Create a room** section adds a Room to the selected region.

<figure><img src="/files/1l9s5u4AlSVHiJgbEv2X" alt="" width="375"><figcaption><p>Create room section of the Rooms Connect dialog</p></figcaption></figure>

This section contains controls for setting a **Room's name** and **maximum player capacity**. Pressing the ***Create*** button will create a Room with the specified parameters and immediately add it to the Room Dropdown above. **Create and Join** will create the Room, and also join it immediately.

## Worlds UI

The **Worlds UI** sample contains a dialog created using Unity UI that can be used to browse and join Worlds hosted in the coherence Cloud or in locally hosted Replication Servers.

### Setup

Before launching the sample scene, you need to either:

1. Start a [Replication Server](/2.3/manual/replication-server) running locally via **coherence > Run Replication Server for Worlds**,
2. or [log in to coherence Cloud](/2.3/getting-started/setup-a-project/test-in-the-cloud) via **coherence > Hub > Cloud > Signup / Login** and select a cloud Project to use.

### Using the sample

The **Worlds Connect Dialog** is a good option to start simple. It simply holds a **dropdown for region selection**, an input field for the **players name**, and a **Connect** button.

<figure><img src="/files/CRpPnnBNS5tmzEnyx5QI" alt="" width="375"><figcaption><p>The Worlds connect dialog</p></figcaption></figure>

If you start a local World Replication Server, it will appear as **LocalWorld**. Similarly if there are Worlds running in the [coherence Cloud](/2.3/hosting/coherence-cloud), they will be listed here.

## Lobbies UI

The **Lobbies UI** sample contains a dialog created using Unity UI that can be used to browse, create and join [Lobbies](/2.3/hosting/coherence-cloud/game-services/lobbies) hosted in the coherence Cloud.

Lobbies are a way to do matchmaking between players for your game.

### Setup

Before launching the sample scene, you need to [log in to coherence Cloud](/2.3/getting-started/setup-a-project/test-in-the-cloud) via **coherence > Hub > Cloud > Signup / Login** and select a cloud Project to use.

You will also need to have at least one **Region** enabled in the **Project Settings** section of your [Online Dashboard](/2.3/hosting/coherence-cloud/online-dashboard).

<figure><img src="/files/wyGRMhmC18eLI98sJjHl" alt=""><figcaption><p>The Lobbies connect dialog</p></figcaption></figure>

## Matchmaking UI

The Matchmaking UI sample contains a dialog created using the UI Toolkit that covers logging into a coherence Cloud [Player Account](/2.3/hosting/coherence-cloud/authentication-service-player-accounts) using a username and password, including our powerful Matchmaking and the coherence Lobbies feature.

You will be able to login or logout from Player Accounts, find suitable Lobbies automatically, integrated chat and persist game sessions even when players close the application.

### Setup

Before launching the sample scene, you need to [log in to coherence Cloud](/2.3/getting-started/setup-a-project/test-in-the-cloud) via **coherence > Hub > Cloud > Signup / Login** and select a cloud Project to use.

You will also need to have at least one **Region** enabled in the **Project Settings** section of your [Online Dashboard](/2.3/hosting/coherence-cloud/online-dashboard).

<figure><img src="/files/MOwBCktKYHICarGVts0H" alt=""><figcaption><p><strong>The Matchmaking connect dialog</strong></p></figcaption></figure>

## Modifying a sample

Samples are copied to your assets folder, in :open\_file\_folder: `Samples/coherence/version_number/`. This means you can change and customize the scripts and Prefabs however you like.

## Upgrading samples

Future versions of **coherence** won't override your changes. If you upgrade to a newer version of **coherence** and import a new sample, they will be imported in a separate folder named after the **coherence** version.

{% hint style="info" %}
If you want the new sample to overwrite the old one, first rename the folder in which the samples are, then import the new version.

The folder to rename is the one that is named after the version number (normally its path would be something like :file\_folder:`Samples/coherence/1.8.0/` for coherence 1.8.0).
{% endhint %}


# Project — First Steps

The basics of coherence

The [First Steps project](https://coherence.io/games/coherence/first-steps-tutorial) contains a series of small sample scenes, each one demonstrating one or more features of **coherence**.

### Scenes

If you're a first time user, we suggest to go through the scenes in the established order. They will guide you through some key **coherence** and networking concepts:

1. [Basic syncing](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing), [animations](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing/1-2-animation-parameters), [sending commands](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing/1-3-sending-commands)
2. [Physics and Authority](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/2-physics-authority-transfer)
3. [Live Queries](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/3-spatial-partitioning)
4. [Parenting entities](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/4-parenting-entities)
5. [Complex entity hierarchies](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/5-complex-hierarchies)
6. [Persistence](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/6-persistence)

Remember that playing the scenes on your own only shows part of the picture. To fully experience the networked aspects, you have to play in one or more built instances alongside the Unity Editor, and even better - with other people.

### Download the Unity project

The Unity project can be downloaded from its [Github repo](https://github.com/coherence/first-steps-tutorial). The [Releases](https://github.com/coherence/first-steps-tutorial/releases) page contains pre-packaged .zip files.

### Try a pre-made build

To quickly try a pre-built version of the game, head to [this link](https://coherence.io/games/coherence/first-steps-tutorial) and either play the WebGL build directly in the browser, or download one of the available desktop versions.

<figure><img src="/files/BJF20dxuhrg0BwR0MKYh" alt=""><figcaption><p>WebGL build hosted directly in the coherence Cloud</p></figcaption></figure>

Share the link with friends and colleagues, and have them join you!

### Make your own build

Once you open the project in the Unity Editor, you can build scenes via *File > Build Settings*, as per usual.

<figure><img src="/files/aa0GVMA190JCUgQTM2Va" alt=""><figcaption><p>Testing out 2 builds and the Unity Editor together, while a local Replication Server runs in the console.</p></figcaption></figure>

{% hint style="success" %}
If you want to try all the scenes in one go, keep them all in the build and place **SceneSelector** as the first one in the list.

If you're working on an individual scene instead, bring that one to the top and deselect the others. The build will be faster.
{% endhint %}

<figure><img src="/files/eAy1FIoIKNg91cELqyhe" alt=""><figcaption><p>Don't forget to bring the scene you're interested in to the top, so it is launched automatically.</p></figcaption></figure>

{% hint style="info" %}
To be able to connect, you need to also run a local Replication Server, that can be started via *coherence > Local Replication Server > Run for Worlds*.
{% endhint %}

You can try running multiple Clients rather than just two, and see how replication works for each of them. You can also have one Client just be the Unity Editor. This allows you to inspect GameObjects while the game runs.

{% hint style="success" %}
Since you might be building frequently, we recommend making native builds (macOS or Windows) as they are created much faster than WebGL.
{% endhint %}

You can also upload a build to the cloud and share a link with friends. To do that, [follow these steps](/2.3/getting-started/setup-a-project/test-in-the-cloud/share-builds) or [watch this quick video](https://www.youtube.com/watch?v=ZYJQzji1Oek) to learn how to host builds on the **coherence** Cloud.


# 1. Basic syncing

This scene demonstrates the simplest networking scenario possible with **coherence**. Characters sync their position and rotation, which immediately creates a feeling of presence. Someone else is connected!

{% tabs %}
{% tab title="Topics covered" %}
[CoherenceSync](/2.3/manual/components/coherence-sync) | Bindings | [Component behaviors](#component-actions) | [Authority](/2.3/manual/networking-state-changes/authority)
{% endtab %}

{% tab title="Game controls" %}

* **WASD** or **Left stick**: Move character
* Hold **Shift** or **Shoulder button left**: Run
* **Spacebar** or **Joypad button down**: Jump
  {% endtab %}
  {% endtabs %}

## In this scene

Upon connecting, a script instantiates a character for you. Now you can move and jump around, and you will see other characters move too.

{% hint style="info" %}
To be able to connect, you need to also run a local Replication Server. that can be started via *coherence > Run Replication Server for Worlds*.
{% endhint %}

<figure><img src="/files/pU69HB9qeR678I2Mc2k2" alt=""><figcaption><p>A local player meets a network-instantiated player.</p></figcaption></figure>

**coherence** takes care of keeping network entities in sync on all Clients. When another Client connects, an instance of your character is instantiated in their scene, and an instance of their character is instantiated into yours. We refer to this as **network instantiation**.

## How it's set up

When you click *Connect* in the sample UI, the `CoherenceBridge` opens a connection. The **PlayerHandler** GameObject on the root of the hierarchy controls character instantiation by responding to that connection event.

<div data-full-width="false"><figure><img src="/files/8e5inyRuwVZjhHlt1uY9" alt=""><figcaption><p>coherenceBridge connects, PlayerHandler responds.</p></figcaption></figure></div>

Its `PlayerHandler` script implements something like this:

```csharp
// PlayerHandler.cs
// Listen to CoherenceBridge events
private void Awake()
{    
    _bridge = FindObjectOfType<CoherenceBridge>();
    _bridge.onConnected.AddListener(OnConnection);
    _bridge.onDisconnected.AddListener(OnDisconnection);
}

// Handle local player lifetime, in response to connection events
private void OnConnection(CoherenceBridge bridge) => SpawnPlayer();
private void OnDisconnection(CoherenceBridge bridge, ConnectionCloseReason reason) => DespawnPlayer();

private void SpawnPlayer()
{
    _player = Instantiate(prefabToSpawn, initialPosition, Quaternion.identity);
}

private void DespawnPlayer()
{
    Destroy(_player);
}
```

On connection, a character is created. On disconnection, the same script destroys the character's instance. Note how instantiating and removing a network entity is done just with regular Unity `Instantiate` and `Destroy`.

Now let's take a look at the Prefab that is being instantiated. You can find it in the `/Prefabs/Characters` folder.

By opening **coherence**'s *Configuration* window (by clicking on the *Configure* button on the `CoherenceSync` component), you can see what is synced over the network.

When this window opens on the *Variables* tab you will notice that, at the very top, `Transform.position` and `Transform.rotation` are checked:

<figure><img src="/files/0wQwn98Rg2BxU5iG28ss" alt=""><figcaption><p>The <em>Variables</em> tab of the <em>Configuration</em> window.</p></figcaption></figure>

This is the data being transferred over the network for this object. Each Client sends the position and rotation of the character that they have authority over to every other connected Client, every time there is a change to it that is significant enough. We call these **bindings**.

Each connected Client receives these values and applies them to the `Transform` component of their own instance of the remote player character.

In First Steps, all the variables are set to public by default. The network code that **coherence** automatically generates can only access public variables and methods, without them being public syncing would not work.

In your own projects, keep it in mind to always set synced variables to public!

### **Component Actions**

To ensure that Clients don't modify the properties of entities they don't have authority over, we need to make sure that they are not running on the character instances that are non-authoritative.

**coherence** offers a rapid way to make this happen. If you open the *Components* tab of the *Configuration* window, you will see that 3 components are configured to do something special:

<figure><img src="/files/jJnKoe9pE2R3UPhRu9vm" alt=""><figcaption><p>The <em>Components</em> tab of the <em>Configuration</em> window.</p></figcaption></figure>

In particular:

* The `PlayerInput` and `KinematicMove` scripts get disabled.
* The `Rigidbody` component is made kinematic.

While in Play Mode, try selecting a remote player character. You will notice that some of its script have been disabled by **coherence**:

<figure><img src="/files/MvcXcRQnGsBn2Sb2v9GE" alt=""><figcaption><p>Player Input and Move have been disabled.</p></figcaption></figure>

{% hint style="info" %}
You can learn more about **Component Actions** [here](https://docs.coherence.io/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/pages/-MYMcuWV2fBpQVo-zzDr#5.-disable-input-on-replicated-object).
{% endhint %}

## Understanding authority

One important concept to get familiar with is the fact that every networked entity exists as a GameObject on every Client currently connected. However, only one of them has what we call **authority** over the network entity, and can control its synced variables.

For instance, if we play this scene with two Clients connected, each one will have 2 player instances in their respective worlds:

<figure><img src="/files/tyCtps03QNdx2Ey2TYU0" alt=""><figcaption><p>A local player character in one Client exists as a remote character on another Client.</p></figcaption></figure>

This is something to keep in mind as you decide which components have to keep running or be disabled on remote instances, in order to not have the same code running unnecessarily on various Clients. This could create a conflict or put the two GameObjects in a very different state, generating unwanted results.

In the Unity Editor, when connected, the name of a GameObject and the icon next to it informs you about its current authority state (see image above).

{% hint style="warning" %}
There are two types of authority in coherence: **State** and **Input**. For the sake of simplicity, in this project we often refer just to a generic "authority", and what we mean is State authority. Go [here](/2.3/manual/networking-state-changes/authority) for more info on authority.
{% endhint %}

If you want to see which entities are currently local and which ones are remote, we included a debug visualization in the project. Hit the **Tab** key (or click the Joystick) to switch to a view that shows authority. You can keep playing the game while in this view, and see how things change (try the [Physics](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/2-physics-authority-transfer) scene!).

<figure><img src="/files/OaNqXIEVe6A8UYtzdtG7" alt=""><figcaption><p>Blue = local, Orange = remote, the rest are non-networked objects.</p></figcaption></figure>


# 1.1 Animation parameters

Using the same scene as in the [previous lesson](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing), let's see how to easily sync animation over the network.

{% tabs %}
{% tab title="Topics covered" %}
[Animation](/2.3/manual/networking-state-changes/animation) | Bindings
{% endtab %}

{% tab title="Game controls" %}

* **WASD** or **Left stick**: Move character
* Hold **Shift** or **Shoulder button left**: Run
* **Spacebar** or **Joypad button down**: Jump
  {% endtab %}
  {% endtabs %}

### In this scene

We haven't mentioned it before, but the character Prefab does a lot more than just syncing its position and rotation.

When you move around, you will notice that animation is also replicated across Clients. This is done via synced Animator parameters (and Network Commands, but we cover these in the [next lesson](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing/1-3-sending-commands)).

<figure><img src="/files/eiUmS6IHzsEtA6tVLkIr" alt=""><figcaption><p>The parameter <em>MoveSpeed</em> makes the player transition from the <em>Idle</em> state to <em>Running.</em></p></figcaption></figure>

Very much like in the example about position and rotation, just sending these across the network allows us to keep animation states in sync, making it look like network-instantiated Prefabs on other Clients are performing the same actions.

### How it's set up

Open the player Prefab located in the `/Prefabs/Characters` folder. Browse its Hierarchy until you find the child GameObject called **Workman**. You will notice it has an `Animator` component.

Select this GameObject and open the *Animator* window.

<figure><img src="/files/uivuctjZdzMUEoQytITK" alt=""><figcaption><p>The Animator controller of the player.</p></figcaption></figure>

As is usually the case, animation is controlled by a few Animator parameters of different types (int, bool, float, etc.).

Make sure to keep the GameObject with the Animator component selected, and open the **coherence** *Configure* window:

<figure><img src="/files/USylIaT8bZZlhLcvqOFi" alt=""><figcaption></figcaption></figure>

You will see that a group of animation parameters are being synced. It's that simple: just checking them will start sending the values across, once the game starts, just like other regular public properties.

{% hint style="info" %}
Did you notice that we are able to configure bindings even if this particular GameObject doesn't have a `CoherenceSync` component on it? This is done via the one attached to the root of the player Prefab.

These parameters on child GameObjects are what we call **deep bindings**.

Learn more in the [Complex hierarchies](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/5-complex-hierarchies) lesson, or on [this page](/2.3/manual/networking-state-changes/child-gameobjects).
{% endhint %}

There is only one piece missing: **animation Triggers**. We use one to trigger the transition to the Jump state.

Since Triggers are not a variable holding a value that changes over time, but rather an action that happens instantaneously, we can't just enable in the *Config* window like with other animator parameters. We will see how to sync them in the [next lesson](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing/1-3-sending-commands), using Network Commands.


# 1.2 Sending commands

Using the same scene as in the [previous lesson](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing), we now take a look at another way to make Clients communicate: Network Commands. Network Commands are commonly referred to as "RPCs" (Remote Procedure Calls) in other networking frameworks. You can think of them as sending messages to objects, instead of syncing the value of a variable.

{% tabs %}
{% tab title="Topics covered" %}
[Network Commands](/2.3/manual/networking-state-changes) | [Animation](/2.3/manual/networking-state-changes/animation)
{% endtab %}

{% tab title="Game controls" %}

* **WASD** or **Left stick**: Move character
* Hold **Shift** or **Shoulder button left**: Run
* **Spacebar** or **Joypad button down**: Jump
* **Q** or **D-pad up**: Wave
  {% endtab %}
  {% endtabs %}

## In this scene

Building on top of previous examples, let's now focus on two key player actions. Press **Space** to jump, or **Q** to greet other players. For both of these actions to play their animation, we need to send a command over the network to invoke `Animator.SetTrigger()` on the other Client.

<figure><img src="/files/mZCs9pawbIVK62SNh1g7" alt=""><figcaption><p>Two connected players waving at each other.</p></figcaption></figure>

## How it's set up

Like before, select the player Prefab located in the `/Prefabs/Characters` folder, and browse its Hierarchy until you find the child GameObject called **Workman**.

Open the **coherence** *Configure* window on the third tab, *Methods*:

<figure><img src="/files/WslO4yaVwm3BY4ZyM8Vj" alt=""><figcaption></figcaption></figure>

You can see how the method `Animator.SetTrigger(string)` has been marked as a Network Command. With this done, it is now possible to invoke it over the network using code.

You can find the code doing so in the `Wave` class (located in `/Scripts/Player/Wave.cs`):

```csharp
sync.SendCommand<Animator>(nameof(Animator.SetTrigger), MessageTarget.Other, "Wave");
```

Analysing this line of code, we can recognize 5 key parts:

* First, notice how the command is invoked on a specific `CoherenceSync` (that `sync` property).
* We want to invoke this command on a component that is an `Animator`.
* We invoke a method called "Animator.SetTrigger".
* With `MessageTarget.Other`, we are asking to send this message only to network entities other than the one that has the `CoherenceSync` we chose to use.
* We pass the string `"Wave"` as the first parameter of the method to invoke.

{% hint style="info" %}
Because we don't invoke this on the one with authority, you will notice that just before invoking the Network Command, we also call `SetTrigger` locally in the usual way:

```
animator.SetTrigger("Wave");
```

An alternative to this would have been to call `CoherenceSync.SendCommand()` with `MessageTarget.All`.
{% endhint %}

In this example we used Network Commands to trigger a transition in an animation state machine, but they can be used to call any instantaneous behavior that has to be replicated over the network. As an example of this, it is also used in the [Persistence](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/6-persistence) lesson to change a number in a UI element across all Clients.


# 2. Physics / Authority transfer

In this sample we look at how to network simple physics simulated directly on the Clients, and the implications of this setup.

{% hint style="info" %}
If we were making a game that relied on precise physics at play between the players (like a sports match, for instance), we would probably go with a setup where the Clients connect to a [Simulator](/2.3/manual/simulation-server) that runs the physics and prevents cheating.

However, that makes running the game much more expensive for the developer, since a Simulator has to be always on.
{% endhint %}

{% tabs %}
{% tab title="Topics covered" %}
Physics | [Authority transfer](/2.3/manual/networking-state-changes/authority/authority-transfer) | Uniqueness | [Persistence](broken://pages/-MYgPvUyuL6aH8ZrwmnB)
{% endtab %}

{% tab title="Game controls" %}

* **WASD** or **Left stick**: Move character
* Hold **Shift** or **Shoulder button left**: Run
* **Spacebar** or **Joypad button down**: Jump
* **E** or **Joypad button left**: Pick up / throw objects
  {% endtab %}
  {% endtabs %}

## In this scene

This scene features a few crates that the players can pick up and throw around. Who runs the physics simulation here? You could say that everyone runs *their part*.

Let's take a closer look at the setup.

## How it's set up

Select one of the crates in the scene. You can see that they have normal `Box Collider` and `Rigidbody` components. Up until a player is connected, they are being simulated locally. In fact if you press Play, they will fall down and settle.

The crates also have a `CoherenceSync` component. The first player to connect gets authority over them, and begins simulating the physics for them.

That Client now syncs 5 values over the network, including the most important ones that will drive the crate's motion: `Transform.position` and `Transform.rotation`.

<figure><img src="/files/0XPyxkPv3V5KVbUZ22wn" alt=""><figcaption><p>5 variables are being synced.</p></figcaption></figure>

On other Clients however (the ones that connect after the first one) these crates will become "remote". Their Rigidbody will become kinematic, so that now their movement is controlled by the authority (i.e. the first Client).

### Authority switch

At this point, the first Client to connect is simulating all the crates. However, if we were to leave things like this, interacting with physical objects that are simulated by another Client would be quite unpleasant due to the lag.

To make it better, other Clients steal authority over crates, whenever they either:

* Touch/collide with a crate directly
* Pick a crate up

In code, this authority switch is a trivial operation, done in a single line. You can find the code in the `Grabbable` class. Essentially, it boils down to this:

```csharp
// Grabbable.cs
if(!_sync.HasStateAuthority)
{
    _sync.RequestAuthority(AuthorityType.Full);
}
```

As you can see, it's good practice to ask first if the requesting script already has authority over an object, to avoid wasted work.

If the request succeeds, the instance of the crate on the requesting Client becomes authoritative, and the Client starts simulating its physics. On the other Client (the previous owner) the object becomes remote (and its Rigidbody kinematic), and is now just receiving position and rotation over the network.

{% hint style="warning" %}
Careful! Since authority request is a network operation, you can't run follow-up code right away after having requested it. It's good practice to set a listener to the events that are available on the Coherence Sync component, like this:

```
_sync.OnStateAuthority.AddListener(OnStateAuthority);
_sync.OnStateRemote.AddListener(OnStateRemote);
```

This way, as soon as the reply comes back, we can perform the rest of the code.
{% endhint %}

{% hint style="info" %}
Also note that while it's totally possible to configure an object so that Clients can just **steal** authority from each other, we configured the crates here to require an authority **request**.
{% endhint %}

When they want authority, Clients have to request it and most importantly, **wait for an answer**.

<figure><img src="/files/Qvj7LnV9usI7xirdfQZG" alt=""><figcaption><p>Authority Transfer settings for the crate Prefab.</p></figcaption></figure>

We implemented this request / answer mechanism to avoid problems of concurrency, where two players are requesting authority on a crate at the same time, and end up with a broken state because the game code assumes that they both got it.

## In conclusion

So **who is running the physics**, after all? We can now say that it's everyone at the same time, as roles change all the time.

As we mentioned in the intro - in a simple game where precise physics are non-crucial this might be enough, and it will definitely keep the costs of running the game down, since no [Simulator](/2.3/manual/simulation-server) has to run in order to make the game playable.

{% hint style="info" %}
As mentioned before, pressing **Tab** (or clicking the Joystick) switches to an authority view. It's very interesting to see how crates switch sides when a player interacts with them.
{% endhint %}

<figure><img src="/files/NVUJq6qaGGK9sjYKcXgc" alt=""><figcaption><p>Blue = crates being simulated on this Client, Orange = remote crates.</p></figcaption></figure>

{% hint style="info" %}
For more on authority, take a look inside the `Grabbable` class. It has more code regarding authority events, all commented.
{% endhint %}

## About uniqueness and persistence

There is one important thing to note in this setup. Since the objects are already in the scene at the start, by default every time a Client connects it would try to sync those instances to the network. This is very similar to what we have seen with character instantiation so far: each Clients brings their own copy.

However, in this case this would effectively duplicate the crates, once online. One extra copy for each connected player! We don't want that.

For this reason, the `CoherenceSync` is configured so that these crates have **No Duplicates**. This is generally the correct way of configuring networked Prefab instances that have been manually placed in the scene.

<figure><img src="/files/5xjUc4zZocPManX8bAao" alt=""><figcaption><p>Lifetime: Persistent, Uniqueness: No Duplicates.</p></figcaption></figure>

In addition to a unique identifier (the **Manual Unique ID**), **coherence** will auto-assign an additional identifier (the **Prefab Instance Unique ID**) whenever the crate is instantiated in the scene at edit time.

With these parameters in mind, the way the crates behave is as follows:

* At the start, none of the entities exist on the Replication Server (yet).
* Client A connects. They sync the crates onto the network. Being unique, the Replication Server takes note of their ID.
* Client B connects. They try to bring the same crates onto the network, but because it is set to be **No Duplicates** and **coherence** finds there is already a network entity with the same ID, it doesn't create a new network entity but recognises that crate as the one on the server, and just makes it non-authoritative for Client B.
* If Client A disconnects, the crates are not destroyed because their **Lifetime** is set to **Persistent**. They briefly become **orphaned** (no one has authority on them) but immediately the authority is passed to Client B due to the option **Auto-adopt Orphan** being on.

{% hint style="info" %}
For more information on persistence, there's [a whole lesson](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/6-persistence) about it.
{% endhint %}

* If everyone disconnects, the crates remain on the Replication Server as network entities that are orphaned. They keep whatever position/rotation they had, since nobody is simulating them anymore.

At this point, nobody is connected. The Replication Server is not doing any work.

* When a new Client reconnects and tries to bring the crates online again, the same thing happens again: the crates in the scene are associated with the orphaned entities and are adopted by the new client, who assumes authority on them.
* They will also most probably see the crates snap to the last seen position/translation that was stored on the Replication Server, which is synced just before they assume full control over the crates.
* At this point, they start simulating their physics locally, like normal.


# 3. Live Queries

Getting updates about every entity in the whole scene is unfeasible for big-world games, like MMOs. For this, **coherence** has a flexible system for filtering entities in your scene based on where they are located, using a tool component called [Live Query](/2.3/manual/components/coherence-live-query).

{% tabs %}
{% tab title="Topics covered" %}
[LiveQuery](/2.3/manual/components/coherence-live-query) | [Optimization](/2.3/manual/optimization)
{% endtab %}

{% tab title="Game controls" %}

* **WASD** or **Left stick**: Move character
* Hold **Shift** or **Shoulder button left**: Run
* **Spacebar** or **Joypad button down**: Jump
  {% endtab %}
  {% endtabs %}

## In this scene

This scene contains two cubes that represent volumes where we want network synchronization to happen. Every connected Client can only see other players if they are standing inside one of these cubes.

<figure><img src="/files/6hVrgVMZUivkmn8TfjIy" alt=""><figcaption><p>Player2 can see Player1 (because they are within a Live Query), but not the opposite.</p></figcaption></figure>

## How it's set up

Select one of the two GameObjects named **LiveQuery**. You will see they have a CoherenceLiveQuery component:

<figure><img src="/files/PWaibQadDb2TGfrk47le" alt=""><figcaption></figcaption></figure>

This component defines an valume (in this case a 10x10x10 cube, 5 is the **Extent**). This is telling the Replication Server that this Client is only interested in network entities that are physically present within this volume.

If a Client has to know about the whole world, set the Live Query to **Infinite**.

{% hint style="success" %}
Now it's clear why `Transform.position` cannot be excluded from synchronization, as we saw in [the first lesson](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing). **coherence** needs to know where network entities are in space at all times, to detect if they fall within a Live Query or not.
{% endhint %}

Live Queries can move in space. They can be parented to the camera, to the player, or to other moving elements.

It is also possible, like in this scene, to have more than one Live Query. They will act as additive, requesting updates from entities that are within at least one of the volumes.

Notice that at least one Live Query is needed: a Client with no Live Query in the scene will receive no updates at all.

{% hint style="info" %}
If you explored previous scenes you might have noticed that GameObjects with a Live Query component were actually there, but in this scene we gave them a special visual representation, just for demo purposes.
{% endhint %}

### Not just visibility

Try moving in and out of volumes. You will notice that network-instantiation takes care of destroying the GameObject representing a remote entity that exits a Live Query, and reinstantiates it when it enters one again.

Also, notice that the player belonging to the local Client doesn't disappear. **coherence** will stop sending updates about this instance to other Clients, but the instance is not destroyed locally, as long as the Client retains authority on it.

{% hint style="warning" %}
If a GameObject can be in a state that needs to be computed somehow, it might not appear correctly in the instant it gets recreated.

For instance, an animation state machine might not be in the correct animation state if it had previously reached that state via a trigger parameter. You would have to ensure that the trigger is called again when the instance gets network-instantiated (via a [Network Command](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/1-basic-syncing/1-3-sending-commands)) or switch your state machine to use other type of animation parameters, which would be automatically synced as soon as the entity gets reinstantiated.
{% endhint %}


# 4. Parenting entities

Every now and then it makes sense to parent network entities to each other, for instance when creating vehicles or an elevator. In this sample scene we'll see what are the implications of that, and how **coherence** uses this to optimize network traffic.

{% tabs %}
{% tab title="Topics covered" %}
Moving platforms | [Local positions](/2.3/manual/networking-state-changes/parenting/direct-children) | [Parenting at runtime](/2.3/manual/networking-state-changes/parenting/direct-children) | [Optimization](/2.3/manual/optimization)
{% endtab %}

{% tab title="Game controls" %}

* **WASD** or **Left stick**: Move character
* Hold **Shift** or **Shoulder button left**: Run
* **Spacebar** or **Joypad button down**: Jump
  {% endtab %}
  {% endtabs %}

## In this scene

This wintery setting contains 2 moving platforms running along splines. Players can jump on them and they will receive the platform's movement and rotation, while still being able to move relative to the platform itself.

<figure><img src="/files/AYsfNWg9R7inmEsp5j76" alt=""><figcaption><p>A player is riding a moving platform, and its Prefab gets parented to it.</p></figcaption></figure>

{% hint style="info" %}
One important note: this sample describes parenting at runtime. For more information on edit-time parenting, see the page about [Nesting Prefabs at Edit time](/2.3/manual/networking-state-changes/parenting/nesting-prefabs-at-edit-time).
{% endhint %}

## How it's set up

This scene doesn't require anything special in terms of network setup to work.

Direct parenting of network entities in **coherence** happens exactly like usual, with a simple `transform.SetParent()`. The player's `Move` script is set to recognize the moving platforms when it lands on them, and it just parents itself to it.

As for the platforms, they are just moving themselves as kinematic rigid bodies, following the path of their spline (see the `FloatingPlatform` script). Their position and rotation is synced on the network, and the first Client to connect assumes authority over them.

<figure><img src="/files/tYgUaQ4rnlgrFxYamzdD" alt=""><figcaption><p>As usual, hitting Tab shows authority. The Client named "player" is currently simulating the platforms.</p></figcaption></figure>

## Effects of parenting entities

Once directly parented, **coherence** automatically switches to sync the child's position and rotation as local, rather than in world space. This means that when child entities don't move within their parent, no data about them is being sent across the network.

Imagine for instance a situation where 3 players are riding one of the platforms and not moving, only the coordinates of the platform are being synced every frame.

### Limitations of simple parenting

You might have noticed we always mentioned "direct" parenting. One limitation of this simple setup is that the parented network entity has to be a first-level child of the parent one. This doesn't exclude that the parent can have other child GameObjects (and other networked entities!), but networked entities have to be a direct child.

A hierarchy could look like this:

* **Platform**
  * **Player**
    * Character graphics
    * Bones
    * ...
  * Platform's graphics
  * ...

(In bold is the root of each Prefab, which has a `CoherenceSync` component)

You can even parent multiple network entities to each other. For example, a networked character holding a networked crate, riding a networked elevator, on a networked spaceship. In that case:

* **Spaceship**
  * **Elevator1**
    * Elevator graphics
  * **Elevator2**
    * **Player**
      * **Crate**
      * Character graphics
    * Elevator graphics
  * Spaceship graphics
  * ...

For cases like these, **coherence** takes care of them automatically. More complex hierarchies require a different handling, and we cover them in [another lesson](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/5-complex-hierarchies).

{% hint style="warning" %}
When parenting entities, it is important that the child's position, rotation, and local scale are replicated so that all Clients see the relative state of the child when connected to a parent. If these properties are not replicated on the child, it is possible that different Clients will see different states of the child relative to the parent.

\
![](/files/WW7AsGJvQNPCx61XEhKi)
{% endhint %}


# 5. Complex hierarchies

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.

{% tabs %}
{% tab title="Topics covered" %}
[Deep bindings](/2.3/manual/networking-state-changes/parenting/deeply-nested-entities) | [Coherence Node](/2.3/manual/networking-state-changes/parenting/deeply-nested-entities)
{% endtab %}

{% tab title="Game controls" %}

* **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
  {% endtab %}
  {% endtabs %}

## 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.

<figure><img src="/files/aNa8GI3FyhBrDTM8Bs8g" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
One important note: this sample describes deep parenting at runtime. For more information on edit-time deep parenting, see the page about [Nesting Prefabs at Edit time](/2.3/manual/networking-state-changes/parenting/nesting-prefabs-at-edit-time).
{% endhint %}

## 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:

<figure><img src="/files/d0vSWwijklc6tZfBZ8ac" alt=""><figcaption><p>The icons in the Hierarchy show the GameObjects that contain bindings.</p></figcaption></figure>

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:

<figure><img src="/files/UGY5En7uWZrFAbHKX3g8" alt=""><figcaption><p>The root syncs only Transform.position (by default) and animation.</p></figcaption></figure>

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:

<figure><img src="/files/s5E9zHzx8YFZnS0q4W2n" alt=""><figcaption><p>The physical base of the arm syncs its rotation</p></figcaption></figure>

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:

<figure><img src="/files/Nm0bbqX5wP8riVZtkWNW" alt=""><figcaption><p>The IK target syncs both position and rotation.</p></figcaption></figure>

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

As mentioned in the lesson about [Parenting Entities](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/4-parenting-entities), 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:

<figure><img src="/files/bcUpPduADfztx0aUQPOu" alt=""><figcaption></figcaption></figure>

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:

<figure><img src="/files/XULGZvHIoYPgOfL3iSPd" alt=""><figcaption><p>The end point of the arm syncs two variables of its Robot Arm Hand script, useful for the grabbing behavior.</p></figcaption></figure>

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

{% hint style="info" %}
Note that **coherence** natively supports syncing references to `CoherenceSync` and `Transform` components, and to GameObjects.
{% endhint %}

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.

Similarly to the crates in the [Physics lesson](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/2-physics-authority-transfer#authority-switch), 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.

**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.

<figure><img src="/files/OPSNQRLOefG22MfbMdqH" alt=""><figcaption><p>Both the robot arm and the crate are currently simulated on this Client.</p></figcaption></figure>


# 6. Persistence

We have seen a lot of examples where objects belonging to a Client would disappear with them when they disconnect. We call these objects **session-based** **entities**.

But **coherence** also has a built-in system to make objects survive the disconnection of a Client, and be ready to be adopted by another Client or a Simulator. We call these objects **persistent**. Persistent objects stay on the Replication Server even if no Client is connected, creating the feeling that the game world is alive beyond an individual player session.

{% tabs %}
{% tab title="Topics covered" %}
[Persistence](broken://pages/-MYgPvUyuL6aH8ZrwmnB) | [Simulator](/2.3/manual/simulation-server) | [Requesting authority](/2.3/manual/networking-state-changes/authority)
{% endtab %}

{% tab title="Game controls" %}

* **WASD** or **Left stick**: Move character
* Hold **Shift** or **Shoulder button left**: Run
* **P** or **Right shoulder button**: Plant a flower (hold to preview placement)
  {% endtab %}
  {% endtabs %}

## In this scene

Players can plant flowers in this little valley. Each flower has 3 phases: starts as a bud, blooms into a full flower, and then withers after some time.

Creating a flower generates a new, persistent network entity. Even if the Client disconnects, the flower will persist on the server. When they reconnect, they will see the flower at their correct stage of growth (this is a little trick [we explain later](#simulating-offline-without-a-simulation-server)).

Planting too many flowers starts erasing older flowers. A button in the UI allows clearing all flowers (belonging to any player) at any time.

<figure><img src="/files/ZlyTeUv4IwSf2C3sg87K" alt=""><figcaption><p>A player about to plant a new flower, surrounded by flowers in different stages.</p></figcaption></figure>

## How it's set up

When using the plant action, any connected player instantiates a copy of the **Flower** Prefab (located in the `/Prefabs/Nature` folder).

By selecting the Prefab asset, we can see its `CoherenceSync` component is set up like this:

<figure><img src="/files/2Wx71z6rV8FK8UIWjKAn" alt=""><figcaption><p>The Flower Prefab's CoherenceSync.</p></figcaption></figure>

In particular, notice how the **Lifetime** property is set to **Persistent**. This means that when the Client who plants a flower disconnects, the network entity won't be automatically destroyed. **Auto-adopt Orphan** set to **on** makes it so the next player who sees the flower instantly adopts it, and keeps simulating its growth.

Opening **coherence**'s *Configuration* window, you will see that we sync position, rotation, and a variable called `timePlanted`:

<figure><img src="/files/LY4kFBvFenOxCFtY2PzK" alt=""><figcaption><p>The setup of the Flower Prefab.</p></figcaption></figure>

When it gets instantiated, the flower writes the current [UNIX timestamp](https://www.unixtimestamp.com/) into the `timePlanted` variable. This variable never changes after this, and is used to reconstruct the phase in which the flower is in (see [below](#simulating-lifetime-without-a-simulation-server)). Similarly, as the flower is not moving, position and rotation are only synced at the time of planting.

Once a flower has spawned, all of its logic runs locally (no **coherence** involved). An internal timer calculates what phase it should be in by looking at the `timePlanted` property and doing the math, and playing the appropriate animations and particles as a result.

### Simulating lifetime without a Simulator

**coherence** supports the ability to have an instance of the game active in the cloud, running some logic all the time (we call this a [Simulator](/2.3/manual/simulation-server)). However, this might be an expensive setup, and it's good advice to think things through differently to keep the cost of running your game lower.

To achieve this, the flowers of this scene store the `Flower.timePlanted` value on the Replication Server. A Replication Server with no connected Clients is dormant, and has a very low cost to run. So when nobody's connected the flowers are not *actually* simulating, they are just waiting.

When a new Client comes online and this value is synced to them, they immediately fast-forward the phase of the flower to the correct value, and then they start simulating locally as normal.

This gives the players the perception that things are still running even when they are not connected.

{% hint style="info" %}
This setup is not bulletproof, and could be easily cheated if a player comes online with a modified Client, changing the algorithm calculating the flowers' phase.

But for a game in which this calculation is not critical, especially if it doesn't affect other player's experience of the game, this can be a nice setup to cut some costs.
{% endhint %}

### Destroying other Clients' flowers

Every Client can, at any time, remove all flowers from the scene by clicking a button in the UI.

<figure><img src="/files/RWT79mf6li3SleyaiGtA" alt=""><figcaption><p>The button to clear the flowers.</p></figcaption></figure>

It's important to remember that you shouldn't call `Destroy()` on a network entity on which the Client doesn't have authority on. To achieve this, we first request authority on remote flowers and listen for a reply. Once obtained it, we destroy them.

Check the code at the end of the `Flower` script:

```csharp
// Flower.cs
public void DestroyRemote()
{
    _sync = GetComponent<CoherenceSync>();
    _sync.OnStateAuthority.AddListener(DestroyThis);
    _sync.RequestAuthority(AuthorityType.Full);
}

private void DestroyThis()
{
    _sync.OnStateAuthority.RemoveListener(DestroyThis);
    Destroy(gameObject, .1f);
}
```

As we discussed in the [Physics lesson](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/2-physics-authority-transfer), switching authority is a network operation that is asynchronous, so we need to wait for the reply from the player who currently has authority.


# Project — Campfire

Advanced networking concepts

Once you have learned the basics using the [First Steps](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial) tutorial project, Campfire is the natural follow-up to get acquainted with more advanced and practical topics.

As with First Steps, you can download the whole Campfire Unity project and explore it at your own pace. Instead of being a series of independent scenes, Campfire is one big scene that presents multiple concepts working together at the same time. We recommend using the pages on this section as guidance on the individual topics, starting with getting acquainted with the [game structure](/2.3/getting-started/samples-and-tutorials/campfire-project/game-mechanics).

### Download the Unity project

The Unity project can be downloaded from its [Github repo](https://github.com/coherence/campfire-tutorial). The *Readme* will tell you the minimum Unity version to use.

### Try a pre-made build

To quickly try out the game, we shared a WebGL build on the [**coherence** Cloud](https://coherence.io/games/coherence/campfire-tutorial). You can play it directly in the browser, or download one of the available desktop versions. Share the link with friends and colleagues, and try it together!

### Play as a Client

To play as a regular Client, make sure that the GameObject called **Simulator** is disabled in the scene **Main**:

<figure><img src="/files/6duPdRUu5Qr09lRKzlfT" alt=""><figcaption><p>Enable/disable the Simulator GameObject as needed</p></figcaption></figure>

Without it, the game will behave as a pure Client and spawn a player character on connection.

#### Making a Client build

If you want to make a game build, simply having that object off will produce a Client build. You can run many Client builds to experience multiplayer gameplay.

### Play as the Simulator

In this project, there is an NPC that is supposed to be controlled by the Simulator (the [Keeper Robot](/2.3/getting-started/samples-and-tutorials/campfire-project/running-a-server-side-npc)). Though this is intended to be a server-side behavior, you can actually make it run locally and play as a player at the same time without modifications to the code.

First, enable the **Simulator** GameObject in the scene.

Secondly, open the **KeeperRobot** prefab contained in :file\_folder:`Prefabs/Characters`. On the `CoherenceSync` component, change its *Simulate In* property to *Client Side*.

<figure><img src="/files/Cx4vJWWMFAMVk4mJnfpT" alt="" width="330"><figcaption></figcaption></figure>

Now press *Play* and connect.

The robot will start acting, exactly like it would do if it were running on a Simulator (minus, of course, the network delay). This allows you to see what would be happening on the server, with the full debugging power of the Unity Editor.

You can even use this Editor instance running alongside one or more Client builds.

#### Building the Simulator

To create a Simulator build, you have two ways to go about it, as usual:

* building a Simulator to launch locally on your machine
* building one to upload on the **coherence** Cloud

In both cases, make sure that the **Simulator** GameObject is enabled in the scene.

Don't change the Keeper Robot's *Simulate In* property like described in the previous section, since to run this behavior on the Simulator we want it to stay *Server Side*.

For more information, refer to the [Simulators: Build and Deploy page](/2.3/manual/simulation-server/build-deploy-simulators).


# Game mechanics

Before we dive into the networking-specific topics, in this introductory page we'll quickly go over how the whole gameplay is structured and set up. We'll cover it both from a point of view of Prefabs and of code so you know where to look for what.

#### Controls

{% tabs %}
{% tab title="Keyboard" %}
**WASD**: Move | **Shift**: Sprint | **Spacebar**: Jump | **E**: Pick up/throw, Chop trees, Sit/stand | **C**: Random appearance | **1**: Wave emote | **2**: Dance | **3**: Yes emote | **4**: No emote | **Enter**: Show chat/send message | **Esc**: Cancel chat
{% endtab %}

{% tab title="Gamepad" %}
**Left stick**: Move | **Left trigger**: Sprint | **Button south**: Jump | **Button west**: Pick up/throw, Chop trees, Sit/stand | **Button east**: Random appearance | **D-pad up**: Wave emote | **D-pad down**: Dance | **D-pad left**: Yes emote | **D-pad right**: No emote | **Select button**: Show/hide chat | **Start button**: Send chat
{% endtab %}
{% endtabs %}

## Player characters, interactions

You'll find the **Player** Prefab in :file\_folder:`Prefabs/Characters`.

When connecting, an instance of the Player is instantiated in the scene by the `PlayerHandler` script, which listens to the corresponding event fired by `CoherenceBridge`.

The player character is a Rigidbody-driven kinematic capsule that is hovering above the ground slightly, and detecting the ground via a raycast. Movement values are provided by the `Move` script on its root, which is in turn informed by the `PlayerInput` component. When instantiated over the network both these components are disabled, and the Rigidbody is set to be kinematic.

Besides movement, other actions are controlled by scripts on three child GameObjects: **Interactions**, **Emotes**, and **Chat**.

<figure><img src="/files/HT8pazGCpj8GPWxG8nvy" alt="" width="563"><figcaption><p>The Player Prefab, with its collider capsule, the interaction trigger, and the world-space UI</p></figcaption></figure>

When approaching an object that can be interacted with, the `InteractionInput` script does the work of detecting objects that have an `Interactable` script, and highlights them by changing their layer. This makes them render with an additional outline, as per one of the passes in the URP Renderer **Renderer\_WorldUI**, contained in :file\_folder:`Settings`.

<figure><img src="/files/hYDwwqbB3TmG4M7zEkQ9" alt="" width="563"><figcaption><p>The three types of interactable objects: trees, chairs, and pick-ups</p></figcaption></figure>

When pressing the interaction key, the right action will be carried on by one of the scripts `ChopAction`, `SitAction`, and `GrabAction`, depending on the type of the object highlighted (a `ChoppableTree`, a `Chair`, or a `Grabbable`).

The chat system is described [here](/2.3/getting-started/samples-and-tutorials/campfire-project/a-simple-text-chat). Other actions are described below.

{% hint style="info" %}
The **Player** Prefab builds on the structure and functionality of the one used in the [First Steps tutorial project](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial), adding more actions. If you find it complex to dive into, try exploring that version first.
{% endhint %}

## Chopping down trees

The prefab for the interactive tree is in :file\_folder:`Prefabs/Interactive`. The log that is spawned by it is in :file\_folder:`Prefabs/Interactive/Burnables`.

The trees have an `Interactable` script that indicates which mesh gets highlighted.

They have an amount of energy that determines the number of times they need to be chopped to be cut down. When they run out, they transition to a chopped state and spawn a tree log. A coroutine makes them spring out again after a certain amount of time.

Read more about how characters interact with remote trees in [this page](/2.3/getting-started/samples-and-tutorials/campfire-project/remote-interactions-trees) about dealing with a non-authority object.

## The campfire

The campfire Prefab is in :file\_folder:`Prefabs/Interactive`.

The campfire is at the center of this demo. Players can burn anything they can pick up by simply throwing the object into it. The campfire exists only in one instance and is pre-placed in the scene, and marked as unique on the network by setting the *Uniqueness* property of its `CoherenceSync` to *No Duplicates*.

Most of the logic of the campfire is in the `Campfire` component. This handles a lot of the networking flow, and can be run by a Client but, if a Simulator connects, they will take over.

In addition to calculating which fire effect to display, it's also in charge of replicating the sound of burning an object on all Clients (read more about effects [here](/2.3/getting-started/samples-and-tutorials/campfire-project/playing-audio-and-particles)).

Learn more about the campfire's logic [on this page](/2.3/getting-started/samples-and-tutorials/campfire-project/a-unique-object-with-complex-state).

## Carrying and burning objects

All non-static interactive objects are in :file\_folder:`Prefabs/Interactive/Burnables`.

They are all Prefab Variants of a base Prefab called **Base\_BurnableObject**, which you can inspect to get a sense of the common functionality.

The objects have several scripts: `Grabbable` provides the ability for them to be picked up, carried and thrown, while `Burnable` grants the ability to be burnt on the campfire.

They have a collider at the root which determines collisions, but a child GameObject named **Interaction** (and its `Interactable` script) has the trigger collider that makes it interactive, and allows to pick the object up. The `Interactable` script also holds a reference to the objects to highlight when the player's interaction trigger intersects the object.

#### Burnable types

<figure><img src="/files/8JDxDg1WtzvBzqaKTiqK" alt=""><figcaption></figcaption></figure>

The logs that are spawned when chopping down trees are not unique, and they are set to *Allow Duplicates*. Check [this page](/2.3/getting-started/samples-and-tutorials/campfire-project/leveraging-object-pooling) for more info on the logs and how they are recycled using an **object pool**.

Instead, the other burnable objects are pre-placed in the scene, and set to be unique (*No Duplicates*): the banjo, the cooler, the bins, the mushrooms, and more. More details on the lifetime of these pre-placed objects in [the section below](#the-server-side-keeper-robot).

## The server-side Keeper Robot

You'll find the robot Prefab in :file\_folder:`Prefabs/Characters`.

The Keeper Robot is an NPC designed to be run by a Simulator (aka, the "server"), to restore the campsite to its initial state even when no-one is connected.

<figure><img src="/files/yn9CdMqxwHYRHUDp7skC" alt="" width="563"><figcaption></figcaption></figure>

Its script will cycle through all unique campfire objects every X seconds. If an object has been destroyed, it will recreate it and put it in its place. If it has been moved, it will just chase it down and put it back into its place.

The way the robot knows about destroyed objects is because the objects, when created the first time, spawn an invisible marker (that we call an "object anchor") which the robot can inspect to know which object has disappeared, and where it was originally placed. The page about [custom instantiation](/2.3/getting-started/samples-and-tutorials/campfire-project/custom-instantiation-and-destruction) has more info on these objects and their anchors.

Read more about this server-side NPC works on its[ dedicated page](/2.3/getting-started/samples-and-tutorials/campfire-project/running-a-server-side-npc).

## Chairs and sitting

You will find chairs in :file\_folder:`Prefabs/Interactive/Chairs`.

<figure><img src="/files/stvbzWU3oSHHsLLIIXZQ" alt="" width="563"><figcaption></figcaption></figure>

Sitting is one of the three actions that can be performed by interacting with objects. It doesn't have networking effects, so it's not covered in this tutorial pages.


# Leveraging object pooling

#### **Topics covered**

[Object pooling](/2.3/manual/networking-state-changes/asset-management#pool-instantiator) | [CoherenceSyncConfigRegistry](/2.3/manual/networking-state-changes/asset-management) | [CoherenceSyncConfig](/2.3/manual/networking-state-changes/asset-management/using-coherencesyncconfig-to-instantiate-gameobjects)

Network entities need to be created and removed all the time. This can be due to entities getting in and out of a LiveQuery, or simply because gameplay requires so. If that is the case, we can leverage **coherence**'s **object pooling** system in order to avoid costly calls to `Instantiate` and `Destroy`, which are famously expensive operations in Unity.

## Our use case

In this project we use pooling for one very clear use case: the tree logs that get spawned when chopping down a tree.

<figure><img src="/files/orKRbGHfRWAgIK5WqIdh" alt=""><figcaption><p>A player just chopped a tree, and a log has been spawned</p></figcaption></figure>

This was a natural choice as players will be chopping trees all the time, but we can also assume that they will burn the logs on the fire almost as often. So by pre-allocating a pool of around 10 logs, we should be covered in most cases.

### Prefab setup

To set up the log to behave like this, all we did was to set that option on the log's own `CoherenceSync` inspector.

Check the **Log** prefab in :file\_folder:`Prefabs/Interactive/Burnable/`:

<figure><img src="/files/XRRrO0Ji7rUkDnnH2sxq" alt=""><figcaption><p>The Log Prefab is set to instantiate from a pool</p></figcaption></figure>

A pool configured like this means that coherence will pre-spawn 10 instances of the Prefab at the beginning of the game.

However if we were to need more, we could request more instances and they would be created and added to the pool. The game can even go above 20. If that were to happen, any instance released beyond 20 wouldn't just be returned to the pool, but would be destroyed.

In other words, 10 and 20 represent **the lower and upper limit for the amount of memory** we are reserving for the logs alone in our game. We are considering anything above 20 as a temporary exception.

When we press Play, coherence instantiates these 10 logs, deactivate them, and put the pool in the **DontDestroyOnLoad** scene:

<div data-full-width="false"><figure><img src="/files/UJgIu3YSD8YY5irb3joy" alt=""><figcaption><p>The object pool for logs, ready to use</p></figcaption></figure></div>

Because they are inactive, their `CoherenceSync` components are not syncing any value.

### Spawning a new log

To spawn a new log we only need to call one line of code. However, we don't provide a reference to a regular Prefab like we would with `Instantiate`. We instead leverage the `CoherenceSyncConfig` object that represents the log.

<figure><img src="/files/ncb3xIdfook9g0YUpoVz" alt=""><figcaption><p>The ChopTree script referencing the log's CoherenceSyncConfig</p></figcaption></figure>

This `CoherenceSyncConfig` contains all the info that **coherence** needs to handle this particular Prefab over the network. If we inspect it, we will notice that it contains in fact how the object is loaded (**Load via**) and how it's instantiated (**Instantiate via**).

<figure><img src="/files/bMD95gE2nRzvh0oVz3kP" alt=""><figcaption><p>The Log's CoherenceSyncConfig</p></figcaption></figure>

You can notice how this is the same info we saw while configuring the `CoherenceSync` before.

This Sync Config can be found in the :file\_folder:`coherence/` folder, and is a sub-object of another ScriptableObject: the `CoherenceSyncConfigRegistry`.

Now that we have a reference to it, we can spawn the log with one line of code. In the `ChoppableTree` script, we do something like:

{% code fullWidth="false" %}

```csharp
CoherenceSync newLog =
    logSyncConfig.GetInstance(transform.position + [...], Quaternion.identity);
```

{% endcode %}

This line looks remarkably similar to Unity's own `Instantiate` in its syntax. The difference is that it gives us back a reference to the `CoherenceSync` attached to the log instance that will be enabled. From this, we can do all sorts of setup operations by just fetching other components with `GetComponent`, to prepare the instance.

### Burning a log

When we are done with it (in this case, when it's thrown into the campfire), we can dispose of it:

{% code fullWidth="false" %}

```csharp
_sync.ReleaseInstance();
```

{% endcode %}

(this line is in the `Burnable.cs` class, inside the `GetBurned()` method)

The instance is then automatically returned into the pool, and disabled.

### Cleaning up

When taking an instance out of the pool or when returning it, **coherence** doesn't automatically do any particular clean up to its state.

As such, when we reuse a pool instance, it is good practice to think of what values should be reset that might have been messed up by previous usage. We should think about what happens during gameplay, and use `OnEnable` / `OnDisable` as needed to ensure that disabled instances are put in a state that makes them ready to be used again.

For this project, since an object can be burned while being carried, we do some cleaning in the `OnDisable` of the `Grabbable.cs` class to prepare the wood logs for another round, like so:

```csharp
private void OnDisable()
{
    isBeingCarried = false;
    _rigidbody.isKinematic = false;
    _collider.enabled = true;
    
    // ... in addition to removing any listener set in OnEnable
}
```


# Remote interactions: Chairs

#### **Topics covered**

[Authority](/2.3/manual/networking-state-changes/authority) | [Authority transfer](/2.3/manual/networking-state-changes/authority/authority-transfer) | [Network Commands](/2.3/manual/networking-state-changes/commands)

In a networked game, an object's logic is always run by one node on the network, whether it's a Client or a Server (which we call a [Simulator](/2.3/manual/simulation-server) in **coherence**). We say that the node "has authority" on the network entity.

There are cases where it makes sense to transfer authority, like it happens in this project with objects that can be picked up. When the player grabs an object, the Client performing it requests authority over the network entity. Once it gets authority it starts running its scripts and has full control over it. This is a very good way to go when only one player can interact with a certain object at a given time.

{% hint style="info" %}
For more info, check [the lesson about transferring authority](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/2-physics-authority-transfer) in the First Steps project.
{% endhint %}

However, there are cases when we don't want to change who has authority on an entity. In the case of an object that many players can interact with at the same time, it wouldn't make sense to continuously move authority between nodes.

The interaction with such remote entities then needs to happen entirely through [Network Commands](/2.3/manual/networking-state-changes/commands).

## Our use case

In this project, it is the case of the chairs placed in the scene. The first Client or Simulator to connect will take authority over them, and it will keep it until they disconnect.

<figure><img src="/files/xSebUZOqDAQ7MssnGQoM" alt=""><figcaption></figcaption></figure>

When a player wants to sit down on a chair, they inform the Authority that they are doing so. The client holding authority will then set the chair as busy, which prevents other players from sitting on it next time they try.

However, for the sake of simplicity and to illustrate the point, we intentionally left this interaction a bit flaky. Can you guess why? What could go wrong with this setup?

### The code

The action originates in `SitAction.cs`:

```csharp
public void Sit(Chair chairComponent)
{
    if (!_chair.isBusy)
    {
        _chair.Occupy();
    }
{
```

`SitAction` checks if the `isBusy` property of the chair is set to `true` (by the authority, of course). If so, it means someone else is already sat on the chair. If `false`, we can sit. So it invokes `Chair.Occupy()`.

You will find the code of chairs in `Chair.cs`, located in :file\_folder:`Scripts/Objects`. Looking into it, we find the property used as a gate:

```csharp
[Sync] public bool isBusy;
```

And further down, the essence of the interaction:

```csharp
public void Occupy()
{
    if (sync.HasStateAuthority) ChangeState(true);
    else sync.SendCommand<Chair>(nameof(ChangeState), MessageTarget.AuthorityOnly, true);
}

public void Free()
{
    if (sync.HasStateAuthority) ChangeState(false);
    else sync.SendCommand<Chair>(nameof(ChangeState), MessageTarget.AuthorityOnly, false);
}

[Command(defaultRouting = MessageTarget.AuthorityOnly)]
public void ChangeState(bool newBusyState)
{
    isBusy = newBusyState;
    // Deactivates the collider so the chair can't be even selected
}
```

So both when occupying a chair (`Occupy()`) or standing up (`Free()`), the player executing the action invokes the `ChangeState` method, either directly or as a Network Command - depending if they are the one with authority.

So one way or the other, `ChangeState` gets executed on the authority, who sets the `isBusy` property to its new value. On the next **coherence** update, the property will be sent to the other Clients.

### What could go wrong?

The answer: Clients are using the `isBusy` property as a check for whether they can sit or not. It is possible that two players will approach a chair at the same time, check if `isBusy` is false (and yes, it will be false), at which point they will inform the authority that want to sit down on it.

The authority performs no additional checks, so you will see both players successfully sitting on the chair, overlapping on each other.

Thankfully we also coded the rest of the interaction so that this doesn't break the game. So while this incidence and the consequences for this interaction are low-risk, if you're looking to create a more robust system it could make sense to implement a check on the authority, and have the Client wait for an answer before they sit down.

We do this in other parts of the demo, like when chopping a tree or when picking up an object. Check the following [section on chopping trees](/2.3/getting-started/samples-and-tutorials/campfire-project/remote-interactions-trees) to explore this similar but more complex use case.


# Remote interactions: Trees

#### **Topics covered**

[Authority](/2.3/manual/networking-state-changes/authority) | [Authority transfer](/2.3/manual/networking-state-changes/authority/authority-transfer) | [Network Commands](/2.3/manual/networking-state-changes/commands)

We saw in the previous section about [sitting on chairs](/2.3/getting-started/samples-and-tutorials/campfire-project/remote-interactions-chairs) how sometimes it makes sense not to move authority around between Clients. At this point, Network Commands are the way to interact with a remote object.

Now let's take a look at another case of remote object, where the interactions with it need to be validated by the one holding authority, to avoid nasty cases of concurrency.

## Our use case

In this project, it is the case of the trees that are placed in the scene. The first Client or Simulator to connect will take authority over them, and it will keep it until they disconnect.

When a player wants to chop a tree, they request the Authority to subtract 1 unit of energy. When the energy runs out, it's the Authority that spawns a new Log instance.

<figure><img src="/files/oDka2FVna2UJAkmCzbaI" alt=""><figcaption><p>A player about to interact with a remote tree</p></figcaption></figure>

This centralization, as opposed to passing authority around, allows multiple players to chop the same tree at the same time and prevents many race conditions, because the important action (destroying the tree and spawning the log) is all resolved on the Client with Authority.

Conceptually, we can imagine the event flow to go like this:

**(1)** Chop action happens on a Client -> **(2)** Authority is notified, elaborates new state -> **(3)** Authority sends result to all others -> **(4)** All other Clients play out animation and effects

### The code

You can find this flow in practice in the `ChoppableTree.cs` script. In this script, only one variable is synchronized, the energy of the tree:

```csharp
[Sync] public int energy = 3;
```

The flow goes like this:

**(1)** A player presses the button to chop down the tree.

It locally invokes the method `TryChop()`, which checks if the tree hasn't been already chopped down, subtracts energy locally, and also invokes the `Chop()` method, locally or remotely depending if authority on this tree is here or not.

```csharp
public void TryChop()
{
    if (energy <= 0) return;
    
    if (sync.HasStateAuthority)
        Chop();
    else
    {
        energy--;
        sync.SendCommand<ChoppableTree>(nameof(Chop), MessageTarget.AuthorityOnly);
    }
}
```

**(2)** On the Authority, the `Chop()` method is called, and checks if the tree needs to be effectively cut down based on its energy:

```csharp
[Command(defaultRouting = MessageTarget.AuthorityOnly)]
public void Chop()
{
    if (energy <= 0) return;
    
    energy--;
    
    if (energy <= 0) CutDown();
}
```

**(3)** If so, `CutDown()` is invoked locally, spawning the log and informing all other clients to play the animation of the tree disappearing:

```csharp
private void CutDown()
{
    ChangeState(false);
    sync.SendCommand<ChoppableTree>(nameof(ChangeState), MessageTarget.Other, false);

    // Spawns log
    StartCoroutine(GenerateNewLog());
    
    // Will grow the tree back in time
    StartCoroutine(GrowBack());
}
```

**(4)** Finally, other Clients play animation, particles and sound locally in `ChangeState()`. They will also see the log spawn thanks to the automatic network-instantiation.

### Changing a synced variable on non-authoritative Clients

Why do we subtract energy from a synced variable in `TryChop()` when we are not the Authority?

Ultimately, the final word on whether the tree has been chopped down completely is always on the Authority's side, of course. But by subtracting energy locally and immediately, we can deal with cases where the player manages to produce two or more chop inputs before the Network Command has travelled to the Authority (and back) with a result.

Imagine: the tree has 1 energy. If we didn't subtract energy locally, the player would be able to chop several times because until the Authority tells them that the tree is down, they still think it has 1 energy.

In fact, it would send several `Chop()` Network Commands for no reason, which the Authority would have do discard on arrival.

Instead, if we immediately change the value on the variable and we use it as an indication of whether we can chop or not this will stop the chopping after one hit, as it should be.

Soon, the Authority will have elaborated on its side that the tree has gone down, and will inform our Client (with `ChangeState()`). Because `energy` is a synced variable, it will be overwritten again with the value computed on the Authority - which of course will be 0 at this point, so it will match.

So nothing is lost and no state is compromised, but with this little trick we get immediate feedback and we avoid some unneeded network traffic.


# A unique object with complex state

#### **Topics covered**

[Network Commands](/2.3/manual/networking-state-changes/commands) | [Seamless authority transfer](#picking-up-when-somebody-leaves) | [Optional server-side logic](#running-this-logic-on-a-server-simulator)

It's often the case that in addition to objects being fully owned by players, like their characters, there is often the need to have objects that exist only in **one copy** in the world and that need to store a complex state that needs to be reflected in the same way on each Client. And the state might not be a simple `int` or `bool` that can be just automatically synced over the network whenever it changes, but something more complex that requires to be elaborated.

This is often the case for more invisible objects like a leaderboard, a spawn point, a score counter or a match timer; but can also be the case for objects that have graphics.

## Our use case

An example of such an object, that also happens to be very central to this demo, is the campfire. As the players pick up objects and throw them on the fire, the campfire needs to perform a calculation based on a timer and the type of the object burned to decide which fire effect to play.

<figure><img src="/files/5PoMPElvKAxq7DQQOBG3" alt=""><figcaption></figcaption></figure>

Timing is key here! If two players throw in two objects, one right after the other, they activate a special effect that makes the campfire burn bigger and brighter. But the two objects need to get on the fire within 2.5 seconds from each other (it's the `teamEffortLength` variable in the `Campfire.cs` script).

Because this calculation depends on the timer value that is managed by the Authority, we can't just independently calculate a result on each Client, as they would almost certainly end up with different results. We need to inform the Authority that the action is taking place, let it figure out the final state, and only then propagate the resulting state and actions to all Clients.

This is in a way similar to [what happens with the trees](/2.3/getting-started/samples-and-tutorials/campfire-project/remote-interactions-trees). The event flow is very similar:

**(1)** Action happens on a Client -> **(2)** Authority campfire is notified, processes result -> **(3)** Authority campfire sends result to all others -> **(4)** Non-authority campfire objects execute local effects

We do have an extra challenge here though. Ultimately we want the Authority to inform everyone to play specific visual and sound effects depending on the object burned. But we can't send Network Commands with a reference to audio assets or particle systems. So we need to change this information to something we can send, and then on the receiving end, "unpack it" and transform it into the info we actually need (i.e., which sound).

{% hint style="info" %}
Right now, we are looking at things in the context of a setup where Authority on the campfire is on one of the Clients. It is totally possible to give the Authority to a Server (and in fact we do in this project, see [the end](#what-if-the-authority-is-on-the-server-simulator) of this page), but the actual logical process doesn't change at all.
{% endhint %}

### The code

If you look into the `Campfire.cs` script, you will find this sequence of actions as exemplified by the flow below:

**(1)** The player throws an object on the fire. `BurnObjectLocal()` is invoked by the `Burnable` that collided with the `Campfire`. The script checks if Authority is already on this Client:

```csharp
public void BurnObjectLocal(CoherenceSync syncToBurn)
{
    //...
    if (_sync.HasStateAuthority)
        BurnObject(syncToBurn.CoherenceSyncConfig.ID);
    else
        _sync.SendCommand<Campfire>(nameof(BurnObject), MessageTarget.AuthorityOnly, syncToBurn.CoherenceSyncConfig.ID);
}
```

The method invoked in both cases is `BurnObject()`, but it's invoked differently depending on whether it is local (direct invocation) or remote (using `SendCommand` via the `CoherenceSync`).

We use the ID of the `CoherenceSyncConfig` of the object that burned as a parameter. The ID is a string, so it's something we can send over the network.

{% hint style="info" %}
For more info on `CoherenceSyncConfig` check out [this page](/2.3/manual/networking-state-changes/asset-management/using-coherencesyncconfig-to-instantiate-gameobjects).
{% endhint %}

**(2)** The logic for which fire effect to play is then calculated in `BurnObject()`.

The campfire uses the `CoherenceSyncConfig` ID as a key to look into the `CoherenceSyncConfigRegistry`, and find the right object archetype to play the right effect.

```csharp
[Command(defaultRouting = MessageTarget.AuthorityOnly)]
public void BurnObject(string syncConfigID)
{
    if (RetrieveBurnableInConfigRegistry(syncConfigID, out Burnable burnable))
    {
        // Did two objects get burned at the same time? Calculate big fire time
        // IsBigFireOn = ...

        ChangeFireState(IsBigFireOn ? burnable.bigFireEffectType : burnable.fireEffectType, syncConfigID);
    }
}
```

{% hint style="info" %}
For more info on `CoherenceSyncConfigRegistry` check out [this page](/2.3/manual/networking-state-changes/asset-management).
{% endhint %}

**(3)** `ChangeFireState()` is invoked locally on the Authority. Here the Authority updates its own property `activeFireEffect` which, being a synced property, gets sent to the other Clients.

```csharp
private void ChangeFireState(FireEffect.EffectType newEffectType, string syncConfigID = "")
{
    // Inform other clients
    _sync.SendCommand<Campfire>(nameof(FireStateChanged), MessageTarget.Other, activeFireEffect, newEffectID, syncConfigID);
    
    // Update synced property
    activeFireEffect = newEffectID;
}
```

But updating that int wouldn't be enough to tell which sound to play, so we send a command to invoke the `FireStateChanged()` method, passing the `CoherenceSyncConfig` ID which the non-authoritative campfire instances can use to trace down the object that burned in the `CoherenceSyncConfigRegistry`.

**(4)** The non-authoritative clients execute `FireStateChanged()`, which turn on/off the appropriate fire particles, and play a specific sound.

### Picking up when somebody leaves

If the Client (or a Simulator) detaining the authority on the campfire disconnects, we need to make sure that whoever gets assigned authority next can pick up the job exactly where it was left off, and continue simulating the campfire logic without interruption.

That's why in the `Campfire.cs` class we make sure to sync three values:

* `activeFireEffect` is an index (expressed as an integer) of which fire effect should be playing right now.
* `fireTimer` and `bigFireTimer` are two countdowns that indicate how much time the fire will still burn normally or, when in "big fire mode", brighter.

However, there's an opportunity to be smart here. `fireTimer` and `bigFireTimer` are variables that are updated every Update on the Authority, but they are only useful in case the Authority gets transferred. So what we can do using the *Optimization* panel is to reduce the frequency they are sent to other Clients to a much more manageable value of once every second.

<figure><img src="/files/tq8kVrbqq71U2lWMhxUD" alt=""><figcaption></figcaption></figure>

This might not be very precise and would have been unacceptable in the case of a visible timer, but here it doesn't matter. To the players this is going to be invisible, but we avoid a lot of network traffic.

### Running this logic on the Server (Simulator)

As mentioned before, this mini state-machine behavior can run perfectly on one of the connected Clients. There is one catch though: this way, if no one is connected, the fire will stop updating because no one is simulating it, and thus it will never burn out.

Try this: connect, throw an object on the fire, disconnect, and reconnect after some time. The value of `fireTimer` will still be the same and so the fire will still be burning no matter how much time has passed.

Using an Authority transfer, it is trivial to let this behaviour run on a Simulator if there is one connected. Look into the `Campfire` class, within `OnLiveQuerySynced`:

```csharp
// ...
if (SimulatorUtility.IsSimulator)
{
    _sync.RequestAuthority(AuthorityType.Full);
}
```

With this simple code, whenever a Simulator connects and sees the persistent campfire network entity, it will take Authority over it. If it were ever to go offline and a client is connected, that Client would take back Authority. If the Simulator comes back online, it would steal it again. And so on.

So, as long as a Simulator is connected, the campfire will keep burning :fire:

{% hint style="success" %}
While this is not a cheat-proof solution, it can be useful for various scenarios.

Having a behavior set up this way allows the Prefab and its logic to be used in an offline mode without modification (because the offline player would act as the owner Client). This can be useful to create a free demo version; a tutorial mode; or even to showcase the game in conditions of limited connectivity.

You could launch the game with no Simulators to run a game preview while keeping costs down, like during an Early Access or a Steam festival. Later on when it goes live, the game could be switched to use a Simulator, and no change to the code would be required.
{% endhint %}


# Custom instantiation and destruction

#### **Topics covered**

Object lifecycle | [Custom instantiators](/2.3/manual/networking-state-changes/asset-management#creating-your-own-instantiator) | Runtime Unique IDs

In many cases, creating and destroying GameObjects like usual will be enough. Just call `Instantiate()` or `Destroy()`, and **coherence** takes care of instantiating and destroying the appropriate Prefab instance on each connected Client.

However, there are moments when it makes sense to customize how exactly **coherence** does this. To take full control over the lifetime of the object, or to attach custom behavior to these events.

**coherence** provides [different object instantiators](/2.3/manual/networking-state-changes/asset-management#coherencesyncconfig-instantiate-via-option) by default (and we use [the Pool Instantiator](/2.3/getting-started/samples-and-tutorials/campfire-project/leveraging-object-pooling) one too), but for ultimate control we also have the ability to create new, completely custom ones.

## Our use case

The campsite in this demo has a few pre-placed unique objects in the scene, that can be picked up, moved, and burned on the campfire.

Until the [Keeper Robot](/2.3/getting-started/samples-and-tutorials/campfire-project/running-a-server-side-npc) comes in and recreates them, they will not be replaced.

<figure><img src="/files/Rq1bGdr1Xip2RE8wE3e0" alt=""><figcaption><p>Some pre-placed objects: the boombox, the banjo, a bin</p></figcaption></figure>

When we burn them, we could in theory just destroy the instance. However the burn code is deeply nested in the `Burnable.cs` class which is used not only by these unique objects, but also by the pooled and non-unique wood logs.

In this method we do this:

```csharp
private IEnumerator GetBurned()
{
    // ...
    _sync.ReleaseInstance();
}
```

A simple `ReleaseInstance()` does the trick for the logs which are non-unique objects. They just go back into the [object pool](/2.3/getting-started/samples-and-tutorials/campfire-project/leveraging-object-pooling).

However, by default unique network entities also get **disabled**, not destroyed. This doesn't work for our special objects!

{% hint style="info" %}
If you're curious about this code, you can check out the file in the coherence package folder in :file\_folder:`io.coherence.sdk/Coherence.Toolkit/CoherenceSyncConfigs/ObjectInstantiators` and open `DefaultInstantiator.cs`
{% endhint %}

We could potentially add an `if` statement in the `GetBurned()` above, detect if the object being destroyed is a log or not, and act differently based on that. Or subclass the `Burnable` and implement overrides for `GetBurned`...

... or we can just create a custom instantiator, and take full control of the object's lifecycle. Let's see the code.

### The custom instantiator

Creating a custom instantiator is trivial. We just need a class to implement the interface `INetworkObjectInstantiator`, like so:

{% code fullWidth="false" %}

```csharp
[Serializable, DisplayName("UniqueBurnableObjects", "Custom instantiator [...]")]
public class UniqueBurnableInstantiator : INetworkObjectInstantiator
{
    // OnUniqueObjectReplaced() does nothing
    
    public ICoherenceSync Instantiate(CoherenceBridge bridge,
                        ICoherenceSync prefab, Vector3 position, Quaternion rotation)
    {
        return Object.Instantiate(prefab as MonoBehaviour,
                                position, rotation) as ICoherenceSync;
    }
    
    public void Destroy(ICoherenceSync obj)
    {
        var monoBehaviour = obj as MonoBehaviour;
        Object.Destroy(monoBehaviour.gameObject);
    }
    
    // WarmUpInstantiator() does nothing
    // OnApplicationQuit() does nothing
}
```

{% endcode %}

The key parts of this script being that on network entity creation a simple `Object.Instantiate()` is performed, and on release `Object.Destroy()`. The other methods (omitted here) are actually empty.

We also want to prepend the class with the `DisplayName` attribute so it shows up in the dropdown when we configure a `CoherenceSync`. Now the *UniqueBurnableObjects* instantiator appears alongside the others in the *Instantiate via* dropdown:

<figure><img src="/files/SVpvNqB4e0CU3wdM7UpS" alt="" width="563"><figcaption></figcaption></figure>

That's it, the instantiator is ready to use.

When we call `ReleaseInstance()` now, it will act differently depending on which instantiator the Prefab is configured to use: the wood logs get disabled, but the unique campfire objects get destroyed.

This was a very simple use case for customization, but it illustrates how easy it can be to get in control of the lifetime of Prefab instances associated to network entities.

{% hint style="info" %}
API Reference for `INetworkObjectInstantiator` can be found [here](https://unityapi.coherence.io/docs/v2.2.0/api/Coherence.Toolkit.INetworkObjectInstantiator.html).
{% endhint %}

### Object anchors

The first time these special unique objects come online, they spawn a persistent invisible object we call "object anchor". This object holds the original position and rotation of the object, so that the [Keeper Robot](/2.3/getting-started/samples-and-tutorials/campfire-project/running-a-server-side-npc) can come in at a later time and put the recreated object back into its place. You could think of these objects as placeholders.

<div><figure><img src="/files/096wBCp9R5eKK0ryndn6" alt=""><figcaption><p>The anchors, created in Play mode</p></figcaption></figure> <figure><img src="/files/yN0k1ATuF2t8BXapc4EV" alt=""><figcaption><p>The Inspector of an anchor holds information about the object it relates to</p></figcaption></figure></div>

One interesting thing we do with anchors is that they are themselves unique objects, but because they are spawned at runtime, they need to get their unique ID dynamically at runtime.

The code is in the `PersistentObject` class:

{% code fullWidth="false" %}

```csharp
private void SpawnAnchor()
{
    // Code simplified for clarity ...

    string uniqueID = _sync.ManualUniqueId;
    _bridge.UniquenessManager.RegisterUniqueId(uniqueID + "-anchor");
    objectAnchorSync = Instantiate(anchorPrefab,
                            transform.position, transform.rotation);
}
```

{% endcode %}

We take the `ManualUniqueId` from the object spawning it (i.e., "Boombox"), and we combine with the string "-anchor" to create a new unique ID, "Boombox-anchor". We register this ID to the `UniquenessManager` of the `CoherenceBridge` to inform it that the next spawned network entity will have that ID. And then we simply call `Instantiate()`.

Because they are set to be *Persistent*, even though a player has burned something and disconnected, the anchors stay on the Replication Server. When a Simulator connects it will find these placeholders and, thanks to the synced properties, will know exactly what to recreate and where to put it.

The check code is in `KeeperRobot.cs`, under `CheckAnchors()` and `ActOnAnchor()`.

First, each anchor's `isObjectPresent` property is used for a quick scan. This property is synced.

If the object is still present, the robot needs to get a reference to it. It calls `GetLinkedObject()` on the anchor, which does this:

```csharp
public GameObject GetLinkedObject()
{
    UniqueObjectReplacement uor =
        _sync.CoherenceBridge.UniquenessManager.TryGetUniqueObject(holdingForUUID);
    bool found = uor.localObject != null;
    return found ? ((CoherenceSync)uor.localObject).gameObject : null;
}
```

Once again using the UUID of the object this anchor is a placeholder for (`holdingForUUID`) as a key, we can now ask the `UniquenessManager` to retrieve an object that has that UUID.

With a reference to this, the robot can now put it back into place using the anchor's position and rotation as a reference.

And if the object has been destroyed (`isObjectPresent` is false), the robot proceeds to recreate it.

```csharp
private Transform RecreateObject(ObjectAnchor objAnchor)
{
    foreach (CoherenceSyncConfig config in configRegistry)
    {
        if (config.ID == objAnchor.syncConfigId)
        {
            _sync.CoherenceBridge.UniquenessManager.RegisterUniqueId(objAnchor.holdingForUUID);
            CoherenceSync newSync = config.GetInstance(holdSocket.position, holdSocket.rotation);
            // ...
        }
    }
    // ...
}
```

Using the anchor's `syncConfigId` as a key, it looks in the `CoherenceSyncConfigRegistry` and finds the archetype to recreate. This is similar to how we used the registry as a catalogue [when dealing with the campfire object](/2.3/getting-started/samples-and-tutorials/campfire-project/a-unique-object-with-complex-state).

After that, like we saw before, the robot registers the newly recreated object with the `UniquenessManager` so that it has the same UUID that it had before being burned.

The object is reinstated, and to a new Client connecting, it will look exactly the same as if it never got removed.


# Running a server-side NPC

#### **Topics covered**

[Simulators](/2.3/manual/simulation-server) | Flexible authority

Even when creating a game that is mainly client-driven, we can still run some of the code on a Simulator. This is very useful to create, for instance, an NPC that operates even when all Clients (players) are disconnected, to give a semblance of a living world.

## Our use case

In this project we used this pattern for the little yellow robot that sits beside the camp. If players move one of the camp's key objects out of place, the robot will tidy up after them. It can even recreate burned objects out of thin air!

<figure><img src="/files/yn9CdMqxwHYRHUDp7skC" alt=""><figcaption><p>The robot in the act of recreating an object</p></figcaption></figure>

Because this behavior is run by a Simulator, even if no-one is connected, given enough time all objects will be back in their place.

### Prefab setup

To setup the robot Prefab to be run by a Simulator couldn't be simpler. The only thing we need to do is to set the *Simulate In* property of the `CoherenceSync` to *Server Side*.

<figure><img src="/files/Cx4vJWWMFAMVk4mJnfpT" alt="" width="375"><figcaption></figcaption></figure>

By just doing so, when you start the game as a Client, the robot GameObject will be deactivated. But if starting as a Simulator (instructions are [here](/2.3/manual/simulation-server/build-deploy-simulators)), it will run.

<figure><img src="/files/ZnnfFoudgSVsJQ59ZhJY" alt="" width="563"><figcaption></figcaption></figure>

We also set both the `KeeperRobot` script and the `NavMeshAgent` to disable on remote instances from the coherence Configuration panel, so they automatically turns themselves off on Client machines.

{% hint style="warning" %}
Note that the GameObject named "Simulator" is disabled by default in the demo scene. When creating a Simulator build, you need to **enable it before building**, or the robot won't appear in the Simulator (and hence, on Clients).

<img src="/files/Us5n54aJpHE2JYKj93UO" alt="" data-size="original">
{% endhint %}

### The code

The code for the robot is all contained in the `KeeperRobot.cs` class, in :file\_folder:`Scripts/Robot`.

Besides the simple state machine code that runs it, only one thing is worth noting here.

The exact moment when the robot starts acting is not in `Start` like usual. We imagined this behavior for an always-on world, so that it could start acting even long after other Clients disconnected. To ensure this, we hook into the `onLiveQuerySynced` event of the `CoherenceBridge`:

```csharp
private void Awake()
{
    _sync = GetComponent<CoherenceSync>();
    _sync.CoherenceBridge.onLiveQuerySynced.AddListener(OnLiveQuerySynced);
}
```

This way, the Simulator has the time to sync up with whatever happened to the campfire objects on the Replication Server, before even beginning to act.

This means that while gameplay can benefit from the presence of this NPC, it's not dependent on it. The Simulator can be always online, or connect and disconnect at times, or to be online only at certain times of the day, and so on.

Coding behaviors like this can open up many creative possibilities in the game's design.

### Hiding code from the Clients

One typical pattern here is to wrap any server-side logic in the conditional compilation directive `#if COHERENCE_SIMULATOR`. This is a great idea especially if the code needs to be obfuscated to normal Client builds, because by doing so, it won't be compiled in the Client at all.

We did it, but we were careful to leave some things out:

```csharp
public class KeeperRobot : MonoBehaviour
{
    // Properties
    // ...

#if COHERENCE_SIMULATOR || UNITY_EDITOR

    // Server-side behaviour
    // Awake, Start, state machine...
    // ...

#endif

    // Network commands to play on non-authoritative instances:
    [Command] public void PlayHumSound() => soundHandler.Play(humLoop);
    [Command] public void PlayVoiceSound() => soundHandler.Play(voices);
    [Command] public void PlayConjure() => soundHandler.Play(objectConjure);
    [Command] public void PlayAppear() => soundHandler.Play(objectAppear);
}
```

As you can see, we left out the 4 Network Commands used to play sounds, and the properties they need to do it. The idea here is that the authoritative instance of the robot, which is running the logic on the Simulator, instructs the non-authoritative instances to play sounds when needed.

Remember that disabling a script only prevents Unity functions to be called (`Awake`, `Start`, `Update`...), but it doesn't prevent invoking its methods.

{% hint style="warning" %}
Besides the above, wrapping synced variables or Network Commands inside a pre-compiler directive would hide them from **coherence** schema baking, effectively creating a different schema for the Simulator, which would then not be able to connect to the RS.

Make sure you keep all data of this type out of the `#if`, so that both Client and Simulator bake the same schema.
{% endhint %}

### Testing server behavior on a Client in the Editor

Finally, you might have noticed how we not only compile this code for Simulator builds, but also when in the Unity editor:

```csharp
#if COHERENCE_SIMULATOR || UNITY_EDITOR
```

This allows us to quickly test the behavior of this robot without adding and removing compilation directives. By simply changing the *Simulate In* property of the `CoherenceSync` to *Client Side*, we can hit the Play button and see the robot move, as if a Simulator was connected.

This is a great way to speed up development and one of the advantages of **coherence**'s flexible authority model: you don't need to code a behavior in a special way to change it from Client to Server side and vice versa.

It is good practice though to switch the robot to *Server Side* again at regular intervals, and test the game by making an actual Simulator build, in order to create the whole network scenario with all its actors.

This will help locate bugs that have to do with timing, connection speed, authority transfers, etc.


# Playing audio and particles

#### **Topics covered**

Networked audio | Networked particles | Animation Events

Usually, visual feedback can be expressed via syncing variables like Animator parameters, positions, and rotations. But sometimes we have the need to play sounds and particles, which are not types that can be automatically set to sync, or that we can send as arguments of [Network Commands](/2.3/manual/networking-state-changes/commands). So how to do it?

## Our use case

This project has a lot of moments where particles and sounds need to play, and we used different strategies for different cases, depending on how fast, repeated, or slow the action is.

#### The simple way: controlling AudioSource or ParticleSystem directly

The most straightforward solution to play a sound is to use a Network Command. Using Commands, you can remotely invoke methods on `AudioSource` or `ParticleSystem` components.

To do that, you could simply open the **coherence** *Configuration* panel (from the `CoherenceSync`), and check the methods you're interested in.

<div><figure><img src="/files/zpssF05gSVn6XtHVpnoF" alt="" width="375"><figcaption><p>The Config panel showing an object with an AudioSource</p></figcaption></figure> <figure><img src="/files/ODLnG8uoS9rYTpKgNggA" alt="" width="375"><figcaption><p>The Config panel showing an object with a Particle System</p></figcaption></figure></div>

While this is a perfectly fine way of doing things, it requires you to call multiple Network Commands in case you wanted to play a sound and particles at the same time. This could lead to desynchronisation between sound and visuals.

As such, in this project we preferred compacting these calls into methods on their own that are invoked as one Network Command, often without parameters to minimize the data being sent across.

### Triggering a sound associated to an action

Connected to the above, let's see how to create our own Network Commands to play sounds (or particles) as a result of an event that happened remotely.

For instance, the [Keeper Robot](/2.3/getting-started/samples-and-tutorials/campfire-project/running-a-server-side-npc) has a series of voices that play whenever it is performing an action. The robots is always controlled by the Simulator, so we need to play sounds on the Clients' devices.

For these sounds, we isolated the sound-playing behavior into Commands of their own. At the end of the `KeeperRobot.cs` class, we have:

```csharp
[Command] public void PlayHumSound() => soundHandler.Play(humLoop);
[Command] public void PlayVoiceSound() => soundHandler.Play(voices);
[Command] public void PlayConjure() => soundHandler.Play(objectConjure);
[Command] public void PlayAppear() => soundHandler.Play(objectAppear);
```

(`soundHandler` is a script attached to the same gameObject)

Each of these methods is invoked as a Network Command, like so:

```csharp
_sync.SendCommand(nameof(PlayVoiceSound), MessageTarget.Other);
```

You can see how we don't play *the sound* over the network, that would be bandwidth-consuming for no reason, but we just communicate *the intention* to play it.

#### Alternative: building an index

Because we only have 4 sounds, we sort of "brute-forced" this, and created an individual Network Command for each sound. This is not a bad idea from the point of view of network traffic: sending a Network Command with no parameter produces less traffic than sending one with.

But it could be unwieldy if we had - say - 100 different sounds to play.

This solution also requires us to bake and produce a new schema if we add or remove one of these Commands. So for a more flexible solution, it could be nice to index the sounds and maybe create a generic Command like:

```csharp
[Command] public void PlaySound(int id) => soundHandler.Play(sounds[id]);
```

In this case though, it was ok to go for individual Commands.

### Audio and particles tied to animations

There are actions that are really quick or short, and asking to play a sound via a command might result in a mismatch between the visuals (an animation) and the sound, due to network delay.

For instance, it wouldn't make sense to send a Command to inform other Clients to play the sound of a footstep. Chances are, by the time they receive the Command, another two-three footsteps have happened.

<figure><img src="/files/8ZR8gb4et1n4rM3amiJr" alt="" width="563"><figcaption></figcaption></figure>

So for footsteps, jump, landing, and more; we used a slightly different strategy. Audio and particles are all played locally as part of the animation, using Unity's own [Animation Events](https://docs.unity3d.com/Manual/script-AnimationWindowEvent.html).

<figure><img src="/files/pA3NtVeKLJWV9w0sScET" alt=""><figcaption><p>Three Animation Events play sounds and particles in the Walk Animation Clip</p></figcaption></figure>

A script called `PlayAnimationEvents.cs` (remember to add it to the same object as the `Animator`!) listens to these events. An example from it:

```csharp
public void PlayJumpEffects()
{
    soundHandler.Play(jumpSFX);
    jumpParticles.Play();
    StopRunParticles();
}
```

This ensures an immediate playback, in sync with the animation. Plus, it produces zero network traffic.

So yes, fun fact: to "network" sounds and particles often you can do without networking anything at all!

{% hint style="success" %}
One more trick! If you have a state machine blending several clips, you might hear **multiple overlapping sounds** when a transition happens. One less known trick is to measure the weight of each clip while executing Animation Events, like we do below:
{% endhint %}

```csharp
public void PlayStepSound(AnimationEvent evt)
{
    if (evt.animatorClipInfo.weight > 0.5)
    {
        soundHandler.Play(footstepSFX);
    }
}
```


# A simple text chat

#### **Topics covered**

Chat | [Lobbies](/2.3/hosting/coherence-cloud/game-services/lobbies)

Communication is an inherent part of online games and a chat, however simple, is a great way to enhance the range of expression for the players.

## Our use case

<div><figure><img src="/files/T1ohivqSESDcMDwT9QSS" alt=""><figcaption><p>The chat composer</p></figcaption></figure> <figure><img src="/files/3q7ktR2OnPBCNrDVABbM" alt="" width="305"><figcaption><p>A chat balloon</p></figcaption></figure></div>

We wanted to implement a very simple chat system. By pressing Enter, a small screen-space UI opens up and allows the player to compose a message. When they press Enter again, a balloon on top of their character displays the message to them, and to all connected Clients.

This is done in three parts.

The `Chat` script on the player reads the input, requests `ChatComposerUI` to display the chat composer that is part of the screen-space scene UI.

When the player sends a chat message, `Chat` is informed by an event sent by `ChatComposerUI`, and sends a Network Command `SendChatMessage` to all other clients.

Finally, the received message is displayed in world-space over the player's head the script `ChatVisualiserUI` present in the **Player** Prefab.

### Getting extra mileage with byte\[]

By default, **coherence**'s Network Commands have a limit in the length that can be sent in one command. This is limited by the length of a UDP packet. While this limitation might be removed in the future, for now it means that chat messages can't be longer than a certain amount.

This amount, however, is quite different depending if you use a parameter of type `string` or of type `byte[]` (byte array). If you send a `string`, you will be able to pass on around 50 characters. This is really not much for a chat system.

If you use `byte[]` though, the number of characters goes up to (around) 500. Now we're talking!

So what we do in this demo is that first we convert the `string` that the player has typed in the UI into a byte array, and we send that via Network Command:

```csharp
private void SendText(InputAction.CallbackContext _)
{
    string message = _chatComposer.GetText();
    if (message != string.Empty)
    {
        byte[] encodedMessage = Encoding.UTF8.GetBytes(message);
        sync.SendCommand<Chat>(nameof(SendChatMessage), MessageTarget.Other, encodedMessage);
    }
    // ...
}
```

Then, on the receiving side, we reconvert it back into a `string`:

```csharp
[Command(defaultRouting = MessageTarget.Other)]
public void SendChatMessage(byte[] encodedMessage)
{
    string decodedMessage = Encoding.UTF8.GetString(encodedMessage);
    chatVisualiser.ShowText(decodedMessage);
    // ...
}
```

This simple trick allows us to send longer messages, or to send the same message generating less traffic.

### Never miss a chat message

Because we are sending the chat messages on the `CoherenceSync` that is on the Player Prefab, it means that if that particular player instance is not visible to a Client because it's outside of their LiveQuery, they won't receive the Network Command and thus the chat message. This is maybe desirable in this demo, where the chat is visualised on top of the player.

But if chat messages are shown in a UI panel and players should receive them all regardless, then it might make more sense to rely on a special type of `CoherenceSync`: [Client Connections](/2.3/manual/client-connections). By sending the Network Command on that, it would ensure that the Command is sent and received regardless of LiveQuery ranges.

{% hint style="info" %}
Read the [Client Connections page](/2.3/manual/client-connections) for more info.
{% endhint %}

### Long-form chats

{% hint style="info" %}
This page talked about a simple chat system to use during gameplay, but keep in mind that **coherence** also has a solution for long-form chats as part of Lobby rooms. Players can be in a lobby before but also during gameplay.

For more information about Lobbies, read [the specific page](/2.3/hosting/coherence-cloud/game-services/lobbies).
{% endhint %}


# Creating a global counter

This document explains how to set up an ever increasing counter that all Clients have access to. This could be used to make sure that everyone can generate unique identifiers, with no chance of ever getting a duplicate.

By being persistent, the counter will also keep its value even if all Clients log off, as long as the Replication Server is running.

{% hint style="info" %}
This sample uses [persistence](broken://pages/-MYgPvUyuL6aH8ZrwmnB) and [uniqueness](/2.3/manual/networking-state-changes/uniqueness).
{% endhint %}

### The Counter

First, create a script called Counter.cs and add the following code to it:

```csharp
using UnityEngine;
using Coherence;
using Coherence.Toolkit;

public class Counter : MonoBehaviour
{
    public int counter = 0;
    public NumberRequester requester;

    public void NextNumber(CoherenceSync requester)
    {
        requester.SendCommand<NumberRequester>(
            nameof(NumberRequester.GotNumber),
            MessageTarget.StateAuthorityOnly,
            counter);
        counter++;
    }
}
```

{% hint style="info" %}
This script expects a command sent from a script called `NumberRequester`, which we will create below.
{% endhint %}

Next, add this script to a Prefab with CoherenceSync on it, and select the `counter`and the method `NextNumber` for syncing in the bindings window. To make the counter behave like we want, set the Prefab's Lifetime to "*Persistent*", set Uniqueness to *"No Duplicates"*, and give it a Manual Unique ID - e.g. "*THE\_COUNTER*". Also enable the "*Auto-Adopt Orphan*".

<figure><img src="/files/SxnCCboadKvcrPSkjvzp" alt=""><figcaption><p>CoherenceSync inspector</p></figcaption></figure>

Finally, make sure that a single instance of this Prefab is placed in the scene.

### NumberRequester

Now, create a script called `NumberRequester.cs`. This will be an example MonoBehaviour that requests a unique number by sending the command `GetNumber` to the Counter Prefab. As a single argument to this command, the `NumberRequester` will send an entity reference to itself. This makes it possible for the Counter to send back a response command (`GotNumber`) with the number that was generated. In this simple example we just log the number to the console.

```csharp
using UnityEngine;
using Coherence;
using Coherence.Toolkit;

public class NumberRequester : MonoBehaviour
{
    CoherenceSync sync;

    private void Awake()
    {
        sync = GetComponent<CoherenceSync>();
    }

    void Update()
    {
        if (sync.HasStateAuthority && Input.GetKeyDown(KeyCode.Return))
        {
            var counter = FindAnyObjectByType<Counter>();
            var counterSync = counter.GetComponent<CoherenceSync>();

            counterSync.SendCommand<Counter>(
                nameof(Counter.NextNumber),
                MessageTarget.StateAuthorityOnly,
                sync);
        }
    }

    public void GotNumber(int number)
    {
        Debug.Log($"Got number: {number}");
    }
}
```

To make this script work, add it to a Prefab that has the CoherenceSync script and mark the `GotNumber` for syncing in the bindings window.


# Video tutorials

{% hint style="info" %}
These videos showcase older versions of coherence.
{% endhint %}

## Getting Started

<table data-column-title-hidden data-view="cards" data-full-width="false"><thead><tr><th data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td></td><td><a href="/files/tZK9BJ6by9tcWzwoJDp8">/files/tZK9BJ6by9tcWzwoJDp8</a></td><td><a href="https://www.youtube.com/watch?v=DXCdYSLpH6U">https://www.youtube.com/watch?v=DXCdYSLpH6U</a></td></tr><tr><td></td><td><a href="/files/yauJ5QjQFNbzgfnzAesG">/files/yauJ5QjQFNbzgfnzAesG</a></td><td><a href="https://www.youtube.com/watch?v=kyUSiBpZ2Bc">https://www.youtube.com/watch?v=kyUSiBpZ2Bc</a></td></tr><tr><td></td><td><a href="/files/qSN2sxrtl0ydTLErfFCX">/files/qSN2sxrtl0ydTLErfFCX</a></td><td><a href="https://www.youtube.com/watch?v=ZYJQzji1Oek">https://www.youtube.com/watch?v=ZYJQzji1Oek</a></td></tr><tr><td></td><td><a href="/files/dCFn2buRkKCBe2wfR8gY">/files/dCFn2buRkKCBe2wfR8gY</a></td><td><a href="https://www.youtube.com/watch?v=v5Ch701Poqg">https://www.youtube.com/watch?v=v5Ch701Poqg</a></td></tr><tr><td></td><td><a href="/files/STKbWBShP3o9THwFojAh">/files/STKbWBShP3o9THwFojAh</a></td><td><a href="https://www.youtube.com/watch?v=4Gyo31dCZX8">https://www.youtube.com/watch?v=4Gyo31dCZX8</a></td></tr></tbody></table>

## High-level Concepts

<table data-column-title-hidden data-view="cards" data-full-width="false"><thead><tr><th data-type="content-ref"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td></td><td><a href="https://www.youtube.com/watch?v=EpIlyg164w8">https://www.youtube.com/watch?v=EpIlyg164w8</a></td><td><a href="/files/CypesGyVBssi2os2SNPz">/files/CypesGyVBssi2os2SNPz</a></td></tr><tr><td></td><td><a href="https://www.youtube.com/watch?v=Ql2w10nJl80">https://www.youtube.com/watch?v=Ql2w10nJl80</a></td><td><a href="/files/SN1mgC3DlKsiR27GhSmc">/files/SN1mgC3DlKsiR27GhSmc</a></td></tr><tr><td></td><td><a href="https://www.youtube.com/watch?v=FG2up5mM_uk">https://www.youtube.com/watch?v=FG2up5mM_uk</a></td><td><a href="/files/r72AShILsXBc9eQ8B0nQ">/files/r72AShILsXBc9eQ8B0nQ</a></td></tr></tbody></table>

## Sample Projects

<table data-view="cards"><thead><tr><th data-type="content-ref"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td></td><td><a href="https://www.youtube.com/watch?v=oA4vyGgj7ao">https://www.youtube.com/watch?v=oA4vyGgj7ao</a></td><td><a href="/files/aCzVRvsBfHPCQX3svLgG">/files/aCzVRvsBfHPCQX3svLgG</a></td></tr><tr><td></td><td><a href="https://www.youtube.com/watch?v=E0GU-BK27R0">https://www.youtube.com/watch?v=E0GU-BK27R0</a></td><td><a href="/files/vmNIhst2P2MIBu3lXzMa">/files/vmNIhst2P2MIBu3lXzMa</a></td></tr><tr><td></td><td><a href="https://youtu.be/RMcJOYjD4jU">https://youtu.be/RMcJOYjD4jU</a></td><td><a href="/files/Qcff4e127EPEHXtqM9fw">/files/Qcff4e127EPEHXtqM9fw</a></td></tr></tbody></table>


# Troubleshooting

<details>

<summary>Can't connect to the Replication Server</summary>

* Is the [Replication Server](/2.3/manual/replication-server) running?
* Is the Replication Server using the same schema as your project?
  * Ensure you have [baked](/2.3/manual/baking-and-code-generation).
  * For local RS, shut down the the Replication Server and launch it again.
  * For cloud RS, ensure you have uploaded the schema to the cloud, then retry.
* Are you on Windows and have text selected in the Command Prompt that is running the Replication Server?
  * Press **Esc** with the Command Prompt having focus to clear any selected text and resume the application.
  * You can also disable the **Quick Edit Mode** in **Command Prompt's Properties** to make it more difficult to accidentally select text. You will then need to select **Edit > Mark** (or press **Ctrl + M**) before you can select text.
* When starting the Replication Server locally, ensure you only have one running on a given port, and that port is not used by any other application.
* If the error persists, get in touch with us.

</details>

<details>

<summary>coherence-related exceptions when entering Play Mode</summary>

Make sure you've [baked](/2.3/manual/baking-and-code-generation) and check on the Networked Prefabs window that your prefabs show no issues.

</details>

<details>

<summary>Networked Prefabs are not being updated</summary>

* Are you connected to the Replication Server? Check the [CoherenceBridge](/2.3/manual/components/coherence-bridge).
* Do you have at least one [CoherenceLiveQuery](/2.3/manual/components/coherence-live-query) in the scene, and is it framing the gameplay?
  * **Tip:** You can set it to radius 0 so it encompasses the whole game space.

</details>

{% hint style="info" %}
Check out our [Known Issues](/2.3/support/known-issues) section.
{% endhint %}


# Frequently asked questions

<details>

<summary>How to stablish a connection</summary>

For a ready-to-use solution, use the Sample UIs accessible from within the coherence Hub. These samples showcase how to connect using Rooms or Worlds, and create connections with a local Replication Server and with a coherence Cloud hosted Replication Server. Otherwise refer to the [Getting Started](/2.3/getting-started/setup-a-project) section or [Replication Server API](/2.3/manual/replication-server/replication-server-api) documentation.

</details>

<details>

<summary>Can't stablish a connection</summary>

* Is a [Replication Server](/2.3/manual/replication-server) running?
* Is the Replication Server using the same schema as your project?
  * Ensure you have [baked](/2.3/manual/baking-and-code-generation).
  * For local RS, shut down the the Replication Server and launch it again.
  * For cloud RS, ensure you have uploaded the schema to the cloud, then retry.
* Are you on Windows and have text selected in the Command Prompt that is running the Replication Server?
  * Press **Esc** with the Command Prompt having focus to clear any selected text and resume the application.
  * You can also disable the **Quick Edit Mode** in **Command Prompt's Properties** to make it more difficult to accidentally select text. You will then need to select **Edit > Mark** (or press **Ctrl + M**) before you can select text.

</details>

<details>

<summary>How to spawn my Player Prefab</summary>

There is no specific "instantiate my player prefab" logic built-in. Any script can instantiate it. You can listen to `CoherenceBridge`'s `onConnected` or `onLiveQuerySynced` events to do your `Instantiate(playerPrefab)`. No calls to any coherence-specific APIs — just a regular `Instantiate`.

</details>

<details>

<summary>How to spawn or destroy a Networked Prefab</summary>

Spawning is done by simply instantiating a prefab that has a CoherenceSync component on it, by using Unity's `Instantiate()` API. Same for removing entities, `Destroy()` the GameObject. Read more about [instantiating and destroying](/2.3/manual/networking-state-changes/instantiate-and-destroy-objects).

</details>

<details>

<summary>How to sync a variable</summary>

You can sync variables on any component attached to a prefab via CoherenceSync component inspector. Click on the Configure button and the Configure window will open. From there, toggle the variables you want to synchronize. These variables will comform the network **state** of the entity.

Only variables of the [supported types](/2.3/manual/networking-state-changes/supported-types) can be synchronized currently.

</details>

<details>

<summary>How to find or iterate through other connected clients</summary>

Refer to [Client Connections](/2.3/manual/client-connections).

</details>

<details>

<summary>How to invoke a method on a client, or on all of them</summary>

Refer to [Commands](/2.3/manual/networking-state-changes/commands).

</details>

<details>

<summary>How to move all connected clients to a new scene together</summary>

To make all connected clients move to a new scene, you can create a method that loads the scene and mark it as a [Command](/2.3/manual/networking-state-changes/commands). Send that command to all targets via `MessageTarget.All`. See also [Scene Management](/2.3/manual/scenes).

</details>

<details>

<summary>How to run a dedicated server for my game</summary>

Dedicated Servers in coherence are called [Simulators](/2.3/manual/simulation-server).

</details>

<details>

<summary>How to do client-side prediction</summary>

[Disable automatic updates](/2.3/manual/networking-state-changes/authority/server-authoritative-setup#client-side-prediction) on the variables you want predict. Implement your prediction code, and listen for incoming updates by [hooking into update callbacks](/2.3/manual/networking-state-changes/authority/server-authoritative-setup#misprediction-and-reconciliation). When the update arrives, you can reconcile the predicted state and the new, incoming sample in a way that fits your game best.

</details>

<details>

<summary>How to create a chat system</summary>

To create a [simple in-game chat](/2.3/getting-started/samples-and-tutorials/campfire-project/a-simple-text-chat) functionality, you can leverage Commands to send strings (or byte arrays) to all connected Clients.

A pre-game chat can also be created by leveraging [Lobbies](/2.3/hosting/coherence-cloud/game-services/lobbies).

</details>


# Networking with CoherenceSync

The `CoherenceSync` component will help you prepare an object for network synchronization. It also exposes APIs that allows us to manipulate the object during runtime.

`CoherenceSync` is able to sync all public variables and methods on any of the attached components, for example Unity components such as `Transform`, `Animator`, etc. This will include any custom scripts, including third-party Asset Store packages that you may have downloaded.

Refer to the [Prefab setup](/2.3/getting-started/setup-a-project/prefab-setup) page to learn how to configure your Prefabs to network state changes.


# Configure window

The Configure Window let's assign **what** to network.

<figure><img src="/files/4czmK1U0DWfAz5lmPJ0e" alt=""><figcaption></figcaption></figure>

#### Variables

Variables selected on this window become network state — they will be replicated to all connected clients automatically.

You can control how these variables are [interpolated](/2.3/manual/networking-state-changes/interpolation) on remote clients, and enable **client prediction**, which doesn't apply updates automatically, letting you decide how.&#x20;

<figure><img src="/files/WOcwwLu60DtOMg2hyEmW" alt=""><figcaption><p>Picking an interpolation to be used for <code>rotation</code></p></figcaption></figure>

<figure><img src="/files/Ggn3cADPS9O4sJCC9Ead" alt=""><figcaption><p>Client prediction allows you to roll updates on your own</p></figcaption></figure>

#### Methods

Methods selected on this window become available as [commands](/2.3/manual/networking-state-changes/commands). You can decide the routing allowed for each method.

<figure><img src="/files/44VqA6F5GkfDaVbyma8A" alt=""><figcaption></figcaption></figure>

#### Components

This section doesn't change what to network — instead, decides what happens when the entity is networked. Specifically, when an entity gains or loses [authority](/2.3/manual/networking-state-changes/authority).

<figure><img src="/files/HIS9hrygsLcjERJ597Nv" alt=""><figcaption></figcaption></figure>

Different component types offer different component actions. You can [write your own](/2.3/manual/networking-state-changes/custom-component-actions).

{% hint style="success" %}
Remember to [bake](/2.3/manual/baking-and-code-generation) when you make changes to your Network Prefabs.
{% endhint %}


# Commands: invoking methods

Invoking methods on remote clients

Commands are methods that can be invoked through the network, from one CoherenceSync to another CoherenceSync. Functionally equivalent to RPCs, commands bind to **public methods** accessible on the **GameObject** hierarchy that **CoherenceSync** sits on.

This video explains how Commands work when invoked on entities:

{% embed url="<https://youtu.be/Ql2w10nJl80?t=300>" %}

You can expose public methods the same way you select fields for synchronization: through the [Configure window](/2.3/manual/networking-state-changes/configure-window) on your **CoherenceSync** component.

<figure><img src="/files/tvpwFaQCwj02pF5hPpVH" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/HMG8XPv1ldtIC3gWfPob" alt=""><figcaption><p>Configure window: Accessible from CoherenceSync Inspector</p></figcaption></figure>

By clicking on the method, you bind to it, defining a command. The grid icon on its right lets you configure the **routing mode**. Commands with a `Send to State Authority Only` mode can be sent only to the state authority of the target CoherenceSync, while ones with the `Send to All Instances` can be broadcasted to all Clients that see it. The routing is enforced by the Replication Server as a security measure, so that outdated or malicious Clients don't break the game.

<figure><img src="/files/MDkA1jdXZoFJnpH2hrZI" alt=""><figcaption><p>Routing mode for a command</p></figcaption></figure>

{% hint style="info" %}
Once commands are added or removed, you must [bake](/2.3/manual/baking-and-code-generation) the change&#x73;**.**
{% endhint %}

### Sending a command

To send a command, call the `SendCommand` method on the **target** `CoherenceSync`.

<pre class="language-csharp" data-overflow="wrap"><code class="lang-csharp">private void OnHit()
{
    var sync = GetComponent&#x3C;CoherenceSync>();
<strong>    sync.SendCommand(TakeDamage, MessageTarget.AuthorityOnly);
</strong>}

[Command]
public void TakeDamage()
{
    Debug.Log("Ouch!");
}
</code></pre>

{% hint style="info" %}
If your Networked Prefab has multiple components of the same type binding to the same method, refer to [sending commands to a specific instance](#sending-a-command-to-a-specific-instance).
{% endhint %}

### Command extensions

Aside from the `SendCommand` method, an extension method is generated for every command when baking. This feature is called **command extensions**.

Such methods take a `MessageTarget` as first argument, followed by the rest of arguments the original method defined. So for example, if you bind to `Foo.Bar()`, you will have a new method `Bar(MessageTarget)` that you can call to convert your method into a command. Here's an example of this approach in practice:

<pre class="language-csharp"><code class="lang-csharp">private void OnHit()
{
<strong>    this.TakeDamage(MessageTarget.AuthorityOnly);
</strong>}

[Command]
public void TakeDamage()
{
    Debug.Log("Ouch!");
}
</code></pre>

This approach is not only easier to write, but also easier to read, and additionally, the intent of who to send to (i.e., the target) is clear right away (in this case, self).

{% hint style="warning" %}
The `MessageTarget` specified when sending the command must be compatible with the **routing mode** set in the bindings, i.e. `Send to State Authority Only` will allow only for the `MessageTarget.StateAuthorityOnly` while `Send to Everyone, including yourself` allows any target.

Also, it is possible that the message never sends as in the case of a command with `MessageTarget.Other` sent from the authority with routing of `State Authority Only.`&#x20;
{% endhint %}

### Configuring command extensions

The settings window has a couple of defines that you can set if you want to change how to command extensions work, or completely disable the feature if you wish to avoid the extra generation.

<figure><img src="/files/G4F55uiKikccJJFayx9I" alt=""><figcaption></figcaption></figure>

Stubs are command extensions that do nothing and are generated alongside the real methods. They are there to avoid compilation errors when commands stop existing, so you have a chance to update your game logic without hitting a compilation deadlock. By default, when your code falls back to these stubs, you will be warned through an compiler obsolete message.

### Sending a command to a specific instance

Command extensions are always explicit about who is the target, so this section only applies to `SendCommand`.

If you have the same command bound more than once in the same Prefab hierarchy, you can target a specific Component when sending a message, via the `SendCommand(Component target)` or `SendCommand(Action action)` overloads. When using the overload that takes an action, it can infer the Component instance associated with it, so you can do `SendCommand(myPlayerRef.TakeDamage)`.

Additionally, if you want to target every component in the hierarchy, you can do so via `SendCommandToChildren`.

### Ordering of commands

By default commands don't have any order. In other words, commands might be received by other Clients in a completely different order than they were sent.

If the order of commands is crucial, use `SendOrderedCommand` instead of `SendCommand`. This guarantees that any given ordered command will be received by other Clients in the same order in which it was sent from the source Client, relative to other sent ordered commands by that Client.

{% hint style="info" %}
Note that ordered commands are not ordered relative to entity creation/destruction or binding updates. They are ordered only relative to other ordered commands.
{% endhint %}

Sending commands as ordered should be used only where necessary, since each ordered command slightly increases bandwidth and latency in case of bad network conditions.

### Receiving a command

We don't have to do anything special to receive the command. The system will simply call the corresponding method on the target network entity.

If the target is a locally simulated entity, `SendCommand` will recognize that and not send a network command, but instead simply call the method directly.

### Command Meta

Commands can carry metadata that provides additional context about when and by whom the command was sent. This is controlled by using `[Command(UseMeta = true)]`.

Command metadata includes:

* **Frame**: The frame number when the command was sent
* **Sender**: The ID of the client that sent the command

#### Enabling Command Meta

To enable metadata for a command, add the `UseMeta = true` parameter to the `[Command]` attribute:

```csharp
[Command(UseMeta = true)]
public void CommandWithMeta()
{
    // Access metadata here
}
```

#### Accessing Command Meta

There are two ways to access command metadata:

**Using CurrentCommandMeta (direct access):**

```csharp
[Command(UseMeta = true)]
public void CommandWithMeta()
{
    var meta = CoherenceSync.CurrentCommandMeta;
    Debug.Log($"Command sent at frame: {meta.Frame}");
    Debug.Log($"Sent by client: {meta.Sender}");
}
```

{% hint style="warning" %}
**Important**: Accessing `CurrentCommandMeta` can throw an exception if accessed outside of a command's context or if 'UseMeta' has not been set to true.
{% endhint %}

**Using TryGetCurrentCommandMeta (safe access):**

```csharp
[Command(UseMeta = true)]
public void CommandWithMetaAndData(string data, int value)
{
    if (CoherenceSync.TryGetCurrentCommandMeta(out var meta))
    {
        Debug.Log($"Command sent at frame: {meta.Frame}");
        Debug.Log($"Sent by client: {meta.Sender}");
        Debug.Log($"Data: {data}, Value: {value}");
    }
}
```

Both methods can be used for commands with or without parameters. The key difference is that `CurrentCommandMeta` provides direct access but can throw exceptions, while `TryGetCurrentCommandMeta` is the safer option that returns a boolean indicating success.

#### When to Use Command Meta

Command meta is useful when you need to:

* Track the timing of command execution for gameplay synchronization
* Identify which client sent a command for security or gameplay purposes
* Implement frame-based game logic that depends on command timing
* Debug network command flow

{% hint style="info" %}
**Performance Note**: Enabling metadata adds a small overhead to command transmission. Only enable it for commands where timing or sender information is actually needed.
{% endhint %}

### Sending a command to multiple CoherenceSyncs

Sometimes you want to inform a bunch of different CoherenceSyncs about a change. For example, an explosion impact on a few players. To do so, we have to go through the instances we want to notify and send commands to each of them.

```csharp
using Coherence;
using Coherence.Toolkit;
using UnityEngine;

public class MyCommands : MonoBehaviour
{
    public void MulticastCommand()
    {
        var self = GetComponent<CoherenceSync>();
        var listeners = FindObjectsByType<CoherenceSync>(); 
        
        foreach (var listener in listeners)
        {
            if (!listener || listener == self)
            {
                continue;
            }
            
            listener.SendCommand<MyCommands>(nameof(ReceiveCommand), 
                MessageTarget.StateAuthorityOnly);
        }
    }

    // bind to this method via the Bindings window
    public void ReceiveCommand()
    {
        Debug.Log("Received!");
    }
}
```

In this example, a command will get sent to each CoherenceSync under the state authority of this Client. To make it only affect CoherenceSyncs within certain criteria, you need to filter to which CoherenceSync you send the command to, on your own.

### Sending null values in command arguments

Some of the primitive types supported are nullable values, this includes:

* Byte\[]
* string
* Entity references: CoherenceSync, Transform, and GameObject

{% hint style="info" %}
Refer to the [supported types](/2.3/manual/networking-state-changes/supported-types) page.
{% endhint %}

In order to send one of these values as a null (or default) we need to use special syntax to ensure the right method signature is resolved.

```csharp
using Coherence;
using Coherence.Toolkit;
using UnityEngine;
using System;

public class MyCommand : MonoBehaviour
{
    private CoherenceSync sync;

    public void MyNullableCommand(string someString, Byte[] someArray)
    {
        if (!string.IsNullOrEmpty(someString)) //Could be null or string.Empty
        {
            // Do something with the string
        }

        if (someArray != null && someArray.Length > 0) //Could be null or Byte[0]
        {
            // Do something with the array
        }
    }

    public void SendNullableCommand()
    {
        sync.SendCommand<MyCommand>(nameof(MyNullableCommand),
            MessageTarget.All,
            (typeof(string), (string)null),
            (typeof(Byte[]), (Byte[])null));
    }
}
```

Null-value arguments need to be passed as a ValueTuple\<Type, object> so that their type can be correctly resolved. In the example above sending a null value for a string is written as:\
\
`(typeof(string), (string)null)`

and the null Byte\[] argument is written as:\
\
`(typeof(Byte[]), (Byte[])null)`

Mis-ordered arguments, type mis-match, or unresolvable types will result in errors logged and the command not being sent.

{% hint style="info" %}
When a null argument is deserialized on a client receiving the command, it is possible that the null value is converted into a non-null default value. For example, sending a null string in a command could result in clients receiving an empty string. As another example, a null Byte\[] argument could be deserialized into an empty Byte\[0] array. So, receiving code should be ready for either a null value or an equivalent default.
{% endhint %}

### Limitations

When a Client receives a command targeted at `StateAuthorityOnly` but it has already transferred an authority of that entity, the command is simply discarded.


# \[Sync] and \[Command]

Aside from configuring your CoherenceSync bindings from within the *Configure* window, it's possible to use the `[Sync]` and `[Command]` C# attributes directly on your scripts. Your Prefabs will get updated to **require** such bindings.

## Sync Attribute

Mark **public** fields and properties to be synchronized over the network.

```csharp
[Sync]
public int health;
```

It's possible to migrate the variable automatically, if you decide to change its definition:

```csharp
[Sync("health")]
public float hp;
```

If a variable is never updated after it is first initialized, it can be flagged to only be synchronized when the GameObject is created. This will improve performance, as **coherence** won't need to continually sample its value for changes like it would normally do.

```csharp
[Sync(DefaultSyncMode = SyncMode.CreationOnly)]
public Color teamColor;
```

### SyncMode.Manual

For fine-grained control over when a variable is synchronized, you can use `SyncMode.Manual`. In this mode, the variable will only be sent over the network when you explicitly call `MarkForSyncing()` on the binding. This is useful for values that change infrequently or only in response to specific events.

{% hint style="info" %}
`SyncMode.Always` is already quite efficient, only performing a lightweight comparison when the binding is ready to sample. In most cases, the default automatic synchronization is sufficient. Consider using `SyncMode.Manual` only when profiling reveals that specific bindings are causing performance issues, or when you have domain knowledge that a value changes very infrequently.
{% endhint %}

```csharp
[Sync(DefaultSyncMode = SyncMode.Manual)]
public byte[] playerSettings;

private CoherenceSync coherenceSync;
private ValueBinding<byte[]> settingsBinding;

private void Awake()
{
    coherenceSync = GetComponent<CoherenceSync>();
    settingsBinding = coherenceSync.GetValueBinding<Player, byte[]>(nameof(playerSettings));
}

public void UpdateSettings(byte[] newSettings)
{
    playerSettings = newSettings;

    // Manually trigger synchronization when settings change
    settingsBinding.MarkForSyncing();
}
```

{% hint style="info" %}
When using `SyncMode.Manual`, it's recommended to disable interpolation on the binding as irregular updates can result in visual artifacts.
{% endhint %}

{% hint style="warning" %}
Be careful not to call `MarkForSyncing()` every frame, as this can result in a much higher sending rate than the default 20Hz sampling rate, leading to excessive bandwidth usage. Only mark bindings for syncing when the value actually changes in a meaningful way.
{% endhint %}

### Switching SyncMode at Runtime

You can change a binding's `SyncMode` at runtime to adapt to different gameplay scenarios. For example, you might want continuous synchronization during active gameplay but manual synchronization during idle periods.

```csharp
[Sync]
public Vector3 targetPosition;

private CoherenceSync coherenceSync;
private ValueBinding<Vector3> targetPositionBinding;

private void Awake()
{
    coherenceSync = GetComponent<CoherenceSync>();
    targetPositionBinding = coherenceSync.GetValueBinding<NetworkedObject, Vector3>(nameof(targetPosition));
}

public void EnableContinuousSync()
{
    // Switch to automatic continuous synchronization
    targetPositionBinding.SyncMode = SyncMode.Always;
}

public void EnableManualSync()
{
    // Switch to manual synchronization for fine-grained control
    targetPositionBinding.SyncMode = SyncMode.Manual;
}

public void UpdateTargetPosition(Vector3 newPosition)
{
    targetPosition = newPosition;

    // Only sync if in manual mode
    if (targetPositionBinding.SyncMode == SyncMode.Manual)
    {
        targetPositionBinding.MarkForSyncing();
    }
}
```

## Command Attribute

Mark **public** methods to be invoked over the network. Method return type must be `void`.

```csharp
[Command]
public void Heal(int amount)
{
    ...
}
```

It's possible to migrate the command automatically, if you decide to change the method signature:

```csharp
[Command("Heal", typeof(int))]
public void IncreaseHp(float hp)
{
    ...
}
```

### Command Meta

Commands can include metadata by setting `UseMeta = true`. This allows access to timing and sender information:

```csharp
[Command(UseMeta = true)]
public void CommandWithMeta()
{
    if (CoherenceSync.TryGetCurrentCommandMeta(out var meta))
    {
        // Access frame timing and sender information
        Debug.Log($"Frame: {meta.Frame}, Sender: {meta.Sender}");
    }
}
```

For more details on using command metadata, see [Command Meta](/2.3/manual/networking-state-changes/commands#command-meta).

{% hint style="warning" %}
Note that **marking** a command attribute only marks it as programmatically usable. It does not mean it will be automatically called over the network when executed.

You still need to follow the guidelines in the [Messaging with Commands](/2.3/manual/networking-state-changes/commands) article to make it work.
{% endhint %}


# \[OnValueSynced]

Notifying State Changes

This attribute triggers a method on remote entities when the variable is changed by the state authority.

Works with [any type supported by coherence](/2.3/manual/networking-state-changes/supported-types).

{% hint style="info" %}
The callback method will be called only for remote instances and **not on the state authority**. We recommend using [properties with a backing field](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties#properties-with-backing-fields) for this.
{% endhint %}

### Usage

Let's start with a simple example:

```csharp
using Coherence.Toolkit;
using UnityEngine;
using UnityEngine.UI;

public class Player : MonoBehaviour
{
    [OnValueSynced(nameof(UpdateHealthLabel))]
    public float Health;

    public Text HealthLabel;

    public void UpdateHealthLabel(float oldHealth, float newHealth)
    {
        HealthLabel.text = newHealth.ToString();
        Debug.Log($"Player HP changed by: {newHealth - oldHealth}");
    }
}
```

Whenever the value of the `Health` field gets updated (synced with its simulated version) the `UpdateHealthLabel` will be called automatically, changing the health label text and printing a log with a health difference.

You can also apply the attribute on the callback method, and give the name of the field instead:

```csharp
[OnValueSynced(nameof(Health))]
public void UpdateHealthLabel(float oldHealth, float newHealth)
```

There's no behaviour difference — it's just a matter of style and preference.

{% hint style="success" %}
For the OnValueSynced attribute to work, the given field or property has to be synchronized over the network, via the [Sync attribute](/2.3/manual/networking-state-changes/sync-and-command-attributes) or via the [Configure window](/2.3/getting-started/setup-a-project/prefab-setup).
{% endhint %}

{% hint style="warning" %}
The `OnValueSynced` attribute targets only members within the given class. That is, there's no way to be notified about a change in the value of a Unity built-in component, like `transform.position`.
{% endhint %}


# Authority

Networked entities can be simulated either on a Game Client ("Client authority") or a Simulator ("Server-side authority"). Authority defines which Client or Simulator is allowed to make changes to the synced properties of an entity, and in general defines who "runs the gameplay code" for that entity.

When an entity is created, the creator is **assigned authority** over the entity. Authority can be then [**transferred**](/2.3/manual/networking-state-changes/authority/authority-transfer) at any time between Clients – or even between Clients and Simulators, or [between Simulators](https://youtu.be/FG2up5mM_uk?si=4sCMOEs_Ic8jtFVw).

In any case, **only one** Client or Simulator can be the authority over the entity at any given time.

To learn more about authority, check out this short video:

{% embed url="<https://youtu.be/Ql2w10nJl80?si=_e9NzhbDtylHrzZL>" %}

{% hint style="info" %}
You can see the basic Authority principles in practice in our[ First Steps](https://coherence.io/games/coherence/first-steps-tutorial) interactive demo. You can read the [explanation](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/2-physics-authority-transfer) as well.
{% endhint %}

## Authority models

When architecting a multiplayer game, it is important to choose which authority model the game relies on. coherence supports a variety of models.

### Distributed Client authority

Client authority is the easiest to set up initially, but it has some **drawbacks**:

* **Higher latency**. Because both Clients have a non-zero ping to the Replication Server, the minimum latency for data replication and commands is the combined ping (Client 1 to Replication Server and Replication Server to Client 2).
* **Higher exposure to cheating**. Because we trust Game Clients to simulate their own Entities, there is a risk that one such Client is tampered with and sends out unrealistic data.

In many cases, especially when not working on a competitive PvP game, these are not really issues and are a perfectly fine choice for the game developer.

Client authority does have a few advantages:

* **Easier to set up**. No Client vs. Server logic separation in the code, no building and uploading of Simulation Servers, everything just works out of the box.
* **Cheaper**. Depending on how optimized the Simulator code is, running a Simulator in the cloud will in most cases incur more costs than just running a Replication Server (which is comparatively very lean).

### Server-side authority

Having one or several [Simulators](/2.3/manual/simulation-server) taking care of important world simulation tasks (like AI, player character state, score, health, etc.) is always a good idea for competitive PvP games. In this scenario, the Simulator has authority over key game elements, like a "game manager", a score-keeping object, and so on.

Running a Simulator in the cloud next to the Replication Server (with the ping between them being negligible) will also result in lower latency.

### Server-side with Client input

A typical choice for competitive games, sometimes called "Server-authoritative". The entity is simulated on the Server, and the Client only sends inputs. To achieve smoother gameplay, the Client can predict the entity's state locally and then reconciliate once the Simulator has come back with a new state.

You can read more about how to achieve this in the section about [Server-authoritative setup](/2.3/manual/networking-state-changes/authority/server-authoritative-setup), or below in the [Input authority](#input-authority) section.

{% hint style="success" %}
**Mixing authority models**

A cool possibility that coherence enables is to mix these modes, since authority is not tied to the match but rather a property of each `CoherenceSync`.

So for instance, you can have a game where some critical entities are server-side with client input for cheat prevention, while others are distributed among Clients. It's up to you!
{% endhint %}

## Authority types

While we generally speak of "authority" in abstract, in the coherence model we break authority in two, in order to support the variety of scenarios needed in multiplayer games. We call these **State authority** and **Input authority**.

A Client or Simulator can only have State authority over an entity, only Input authority, or both (in this case we say it has "full authority"). In fact, if you use coherence on a basic level, most of the time you will be dealing with full authority without realising it.

### State authority

When a Client has State authority over an entity it means that they are authorized to change its state, that is, the values of the entity's networked properties.

For instance, if the entity's `Transform.position` and `Transform.rotation` properties are set to sync, the Client who has authority can change these and move the entity around.

A Client who tries to change properties with no State authority will see those properties be reset immediately by coherence.

{% hint style="info" %}
**Hint:** If you see an entity jittering around, it might be the signal that the current Client has no authority over an entity, but it's trying to change its values. Time to do some debugging!
{% endhint %}

### Input authority

When a Client or Simulator has Input authority over an entity, it means that they are authorized to send inputs to the State authority.

Whoever has State authority then is in charge of processing that input, and producing a new state for the entity, which is then sent to all observing Clients.

Splitting Input and State authority is a common pattern when creating a [server-authoritative setup](/2.3/manual/networking-state-changes/authority/server-authoritative-setup).

## Special authority states

### Orphans

Entities that no-one has authority over (neither State nor Input) are called "orphans". Orphaned entities are not simulated, so the values of their synced properties don't change. In a way you could think of them as sleeping.

Authority over an entity can be given up using `CoherenceSync.AbandonAuthority()`. Using this API will make an entity orphan until someone else adopts it. An entity can also become an orphan when a Client or Simulator that had State authority disconnects.

To change the state of an orphan entity, someone has to take State authority over them. This is done either automatically when an orphan is seen for the first time (only if the entity is set to be on [**Auto-Adopt Orphan**](/2.3/manual/networking-state-changes/authority/authority-transfer#auto-adopt-orphan)), or intentionally, using the API `CoherenceSync.Adopt()`.

{% hint style="info" %}
For an entity to become an orphan, they need to be set as **Persistent**. A non-persistent entity that is abandoned will be immediately deleted by the Replication Server.
{% endhint %}

### **Remote entities**

When a Client has no authority whatsoever over an entity, we often refer to that entity as "remote". It's important to understand that a remote entity is only remote to some of the Clients, so "remote" is not a authority state in itself, but just a way to refer to an entity from the point of view of a certain Client.

For instance, an entity seen as remote by Client A might be:

* Authoritative on some other Client B or C, or on Simulator A, etc.
* If no one has authority over it, it is an [orphan](#orphans).

Even if an entity is not currently being simulated locally (the Client does not have authority), we can still affect its state by sending a [network command](/2.3/manual/networking-state-changes/commands) or even [requesting a transfer of authority](/2.3/manual/networking-state-changes/authority/authority-transfer).

{% hint style="success" %}
**Authority in practice**

To recap all possibilities with an example, consider the following case. We're creating a competitive 1v1 robot fighting game in a big arena.

* **Client A** has Input authority over their mech robot.
* **Client B** also has Input authority over their robot.
* The **Simulator Server** in charge of the match has State authority over both mechs, so they can't cheat.
* **Client A** sees the robot belonging to **Client B** as a remote entity.
* The same happens to **Client B**: they see **Client A**'s robot as remote.
* Authority [transfer](/2.3/manual/networking-state-changes/authority/authority-transfer) has been disabled for the robot mechs, so even if cheating, Clients couldn't be stealing authority from each other.
* **Client A** also has State authority over some cosmetic items they are wearing.
* They can turn them on/off at any time by enabling/disabling the MeshRenderer component, or literally remove them and leave them on the ground.
* If **Client A** drops an item to the ground, the entity gets abandoned by them. It is now an orphan, and won't move for the duration of the match.
* If **Client B** finds the cosmetic item and picks it up, they will adopt it and can now wear it on themselves.

We hope that using this example you can see all the possibilities that a flexible authority system can provide.
{% endhint %}


# Authority transfer

Authority over an entity is **transferrable**, so it is possible to move the authority between different Clients or even to a Simulator. This is useful for things such as balancing the simulation load, or for exchanging items. It is possible for an entity to have no Client or Simulator as the authority - these entities are considered orphaned and are not simulated.

## Types of authority transfer

In the design phase, **CoherenceSync** objects can be configured to handle authority transfer in different ways:

* **Request**. Authority transfer may be requested, but it may be rejected by the current authority.
* **Steal.** Authority will always be given to the requesting party on a FCFS ("first come first serve") basis.
* **Not transferable**. Authority cannot be transferred.

{% hint style="info" %}
Using the **Not transferable** option will also disable giving the authority to other Clients, even if you own the entity.

If you want to instantiate entities on the host or Simulator and then transfer the authority to a Client, it is recommended to use the **Request** option, with **Approve by Default** set to false.
{% endhint %}

<figure><img src="/files/DMobIu89GR6aF7Wfyugt" alt=""><figcaption></figcaption></figure>

When using the Request mode, you can use `CoherenceSync.OnAuthorityRequest` to decide which transfers should go through.

```csharp
using UnityEngine;
using Coherence.Toolkit;
using Coherence;

public class AuthorityTransferRequestApproval : MonoBehaviour
{
    public CoherenceSync sync;

    private void Awake()
    {
        sync.OnAuthorityRequest.AddListener(OnAuthorityRequest);
    }

    private void OnAuthorityRequest(AuthorityRequest request, CoherenceSync sync)
    {
        // In this example, we want to only allow input authority to be transferred.
        request.Respond(request.AuthorityType == AuthorityType.Input);
    }
}
```

### Auto-adopt Orphan

When **Lifetime** is set to **Persistent**, you will see an extra checkbox called **Auto-adopt Orphan**.

Enabling this option makes it so that if an entity is abandoned by its owner, the Replication Server will assign it to a Client again, as soon as possible. For instance, this can be useful in a big game world, where entities often go out of LiveQueries. When they are first seen again by a Client, the **Auto-adopt Orphan** option ensures that the Client takes over that entity (i.e. its State authority) without you having to write code for it.

{% hint style="warning" %}
**Note:** If you abandon an entity but it's still in your LiveQuery, on the next frame the Replication Server might assign it to you again. If you want more control over that, then perhaps you should turn **Auto-adopt Orphan** off, and implement callbacks to the authority events for that entity.
{% endhint %}

## Requesting authority in code

Requesting authority is very straightforward.

```csharp
var result = await sync.RequestAuthorityAsync(AuthorityType.Full);

if (result)
{
    Debug.Log("Successfully acquired authority.");
}
else
{
    Debug.Log($"Failed to acquire authority: {result.FailureMessage}");
}
```

`RequestAuthorityAsync` returns a result with Type `Success` if the request was successful, or one of the result listed below if it was not:

* **Canceled**: either the networked entity was destroyed while the request was in progress, or a custom [CancellationToken](https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-cancellation) was passed to the method and used to cancel the request before it completed.
* **Entity Not Synchronized With Network**: the entity is not being networked (its CoherenceBridge is not connected to a room or a world).
* **Entity Orphaned Error**: the entity is orphaned, in which case you must call `CoherenceSync.Adopt` instead to request authority.
* **Entity Not Transferable Error**: the entity is not allowed to be transferred because its `Authority Transfer` has been set to `Non Transferable`.
* **Request Rejected Error**: this can happen if `Authority Transfer` has been set to `Request` and the client or server that holds authority over the entity rejected the request.
* **Already Has Authority Error**: the client already has the requested authority over the entity.
* **Invalid Authority Type Error**: the requested authority type is not supported. This can happen if a request is made to acquire authority of type `None` . `CoherenceSync.AbandonAuthority` can be used to give up authority (orphaning the entity) instead.
* **Entity Is Client Connection Error**: the entity is created by the [Client Connection](/2.3/manual/client-connections) for the client making the authority request.
* **Timeout Error**: the request was not approved or rejected by the server within 10 seconds. This is fail-safe so that the request is always guaranteed to complete.

Because of the asynchronous nature of the authority request, clients can receive [commands](/2.3/manual/networking-state-changes/commands) for entities that they no longer have authority over. Such commands are dropped.

In addition to awaiting `Task<RequestAuthorityResult>` returned by `CoherenceSync.RequestAuthorityAsync`, you can also get notified about authority requests being made (`OnAuthorityRequest`), authority requests being rejected (`OnAuthorityRequestRejected`), and state or input authority being acquired (`OnStateAuthority` / `OnInputAuthority`) or lost (`OnStateRemote` / `OnInputRemote`) via **UnityEvents** on the **CoherenceSync.**

<figure><img src="/files/t4fkSUZzlq1dpOxPcHci" alt=""><figcaption></figcaption></figure>


# Server-authoritative setup

Sometimes, distributing authority is not the way to go. Certain types of games require a model where the server (or, we should say, the [**Simulator**](/2.3/manual/simulation-server)) is in control of the simulation of the whole game, and the players only send inputs to it. The Simulator elaborates these inputs, and in response updates the Client about the new game state.

This way of doing things is usually referred to as **server-authoritative**.

## When to use a server-authoritative setup?

* **In competitive games**. Many game genres use client inputs and centralized simulation to guarantee the fairness of actions or the stability of physics simulations.
* **In situations where Clients have low processing power**. If the Clients don't have sufficient processing power to simulate the World it makes sense to send inputs and just display the replicated results on the Clients.
* **In situations where determinism is important**. RTS and fighting games can use **CoherenceInput** component and [rollback](/2.3/manual/advanced-topics/competitive-games/determinism-prediction-rollback) to process input events in a shared (not centralized) and deterministic way so that all Clients simulate the same conditions and produce the same results.

{% hint style="info" %}
**coherence** currently only supports using **CoherenceInput** in a centralized way, where a single Simulator is setup to process all inputs and replicate the results to all Clients.
{% endhint %}

## Setup CoherenceInput

Setting up an object for server-side simulation using [**CoherenceInput**](/2.3/manual/components/coherenceinput) is done in **three** steps:

### 1. Set the Simulation type

The *Simulate* property needs to be set to *Server Side with Client Input.*

<figure><img src="/files/XyIiUsQWtBSiIpZKif5P" alt=""><figcaption><p>The "Server Side With Client Input" option in CoherenceSync Inspector</p></figcaption></figure>

At this point, a **CoherenceInput** component is automatically added to the object.

Setting the simulation type to this mode instructs the Client to automatically transfer **State Authority** for this object to the [Simulator](/2.3/manual/simulation-server) that is in charge of simulating inputs on all objects, and only retain **Input Authority**.

### 2. Declaring Inputs

Each simulated **CoherenceSync** component is able to define its own, unique set of inputs via the **CoherenceInput** interface.

An input can be of types:

* **Button**. A button input is tracked with just a binary on/off state.
* **Axis / Axis2D / Axis3D**. An axis input is tracked as one/two/three floats from -1 to 1.
* **String**. A string value representing custom input state. (max length of 63 characters)
* **Rotation**. A rotation is represented by a Quaternion.
* **Integer**. Represented as an int.

![Two inputs have been added, named Move and Shoot](/files/AzxXl5wAyWqCjX0kSACt)

### **3. Bake the netcode**

In order for the inputs to be used, they must be [baked](/2.3/manual/baking-and-code-generation).

{% hint style="info" %}
If the **CoherenceInput** fields or name is changed, then the **CoherenceSync** object must be re-baked to reflect the new fields/values.
{% endhint %}

## Using CoherenceInput

When a Simulator is running it will find objects that are set up using **CoherenceInput** components and will automatically take over State Authority, and start simulating them.

During gameplay, scripts from both the Client and Simulator work with the inputs defined on the **CoherenceInput** of the replicated object: the Client uses the `Set*` methods to set input values, and the Simulator uses the `Get*` methods to access them.

In all of these methods, the `name` parameter is the same as the **Name** field defined on the **CoherenceInput** component.

{% hint style="info" %}
Check the [CoherenceInput API](https://unityapi.coherence.io/docs/v2.2.0/api/Coherence.Toolkit.CoherenceInput.html) for a complete list of the available methods.
{% endhint %}

Here's an example of a Player using CoherenceInput, reading input from Unity's legacy Input Manager:

```csharp
public class Player : MonoBehaviour
{
    public CoherenceSync coherenceSync;

    void Awake()
    {
        coherenceSync = GetComponent<CoherenceSync>();
    }

    void Update()
    {
        // This code will run on the client
        if (coherenceSync.HasInputAuthority)
        {
            SendInputs();
        }

        // This code will run on the simulator
        if (coherenceSync.HasStateAuthority)
        {
            ProcessInputs();
        }
    }

    void SendInputs()
    {
        var jump = Input.GetButton("Jump");
        coherenceSync.Input.SetButton("Jump", jump);

        var moveX = Input.GetAxis("Horizontal");
        var moveY = Input.GetAxis("Vertical");
        var move = new Vector2(moveX, moveY);
        coherenceSync.Input.SetAxis2D("Move", move);
    }

    void ProcessInputs()
    {
        var jump = coherenceSync.Input.GetButton("Jump");
        /* Apply jumping logic here */

        var move = coherenceSync.Input.GetAxis2D("Move");
        /* Apply movement logic here */
    }
}
```

## Input Authority

Each object only accepts inputs from one specific Client, called the object's **Input Authority**.

When a Client spawns an object it automatically becomes the **Input Authority** for that object. The object's creator will retain control over the object even after State Authority has been transferred to the Simulator.

If an object is spawned directly by the Simulator, you will need to assign the **Input Authority** manually. Use the `TransferAuthority` method on the **CoherenceSync** component to assign or re-assign a Client that will take control of the object:

```csharp
public void AssignNewInputAuthority(CoherenceClientConnection newInputOwner)
{
    var coherenceSync = GetComponent<CoherenceSync>();
    coherenceSync.TransferAuthority(newInputOwner.ClientId, AuthorityType.Input);
}
```

The **ClientId** used to specify Input Authority can currently only be accessed from the **ClientConnection** class. For detailed information about setting up the ClientConnection Prefab, see the [Client Connections](/2.3/manual/client-connections) page.

{% hint style="info" %}
Use the `OnInputAuthority` and `OnInputRemote` events on the `CoherenceSync` component to be notified whenever an object changes input authority.
{% endhint %}

{% hint style="warning" %}
Only the object's current State Authority is allowed to transfer Input Authority.
{% endhint %}

Additionally, it is possible to send a [command](/2.3/manual/networking-state-changes/commands) directly to the input authority using the `MessageTarget.InputAuthorityOnly` message target in the send command parameters. This allows Clients to communicate with the input "owner" of an entity even when the state "owner" is a different Client or Simulator.

The `OnInputSimulatorConnected` event can also be raised on the Simulator or host if they have both Input and State Authority over an entity. This allows the session host to use inputs just like any other client but might be undesirable if input entities are created on the host and then have their Input Authority transferred to the clients.

To solve this you can check the **CoherenceSync.IsSimulatorOrHost** flag in the callback:

```csharp
coherenceSync.OnInputSimulatorConnected.AddListener(() =>
{
    if (coherenceSync.Bridge.IsSimulatorOrHost)
    {
        // Ignore for Simulators and hosts.
        return;
    }

    // Insert your game logic here
    Debug.Log("Input ready for use!");
});
```

## Client-side prediction

Compared to Client-side simulation, server-side simulation takes a **significantly longer time** from the Client providing input until the game state is updated. That's because of the time required for the input to be sent to the Simulator, processed, and then the updates to the object returned across the network. This round-trip time results in an **input lag** that can make controls feel awkward and slow to respond.

If you want to use a server-authoritative setup without sacrificing input responsiveness, you need to use Client-side prediction.

With Client-side prediction is enabled for a binding, **incoming network data is ignored**, allowing the Client to calculate (predict) its value locally. A typical use case is to predict position and rotation for the local player, but you can toggle Client-side prediction for any binding in the *Configuration* window:

<figure><img src="/files/9nCVQ7DlPlah9MxacjF6" alt="" width="563"><figcaption><p>The position binding will be predicted only if the object has Input authority</p></figcaption></figure>

By processing inputs both on the Client and on the server, the Client can make a prediction of where the player is heading without having to wait for the authoritative server response. This provides immediate input feedback and a more responsive playing experience.

Note that inputs should not be processed for Clients that neither have **State Authority** nor **Input Authority**. That's because we can only predict the local player; remote players and other networked objects are synced just as normal.

```csharp
public void Update()
{
    if (coherenceSync.HasStateAuthority || coherenceSync.HasInputAuthority)
    {
        ProcessMousePosition();
    }

    if (coherenceSync.HasInputAuthority)
    {
        SendMousePosition();
    }
}
```

### Misprediction and Reconciliation

With Client-side prediction enabled, the predicted Client state will sometimes diverge from the server state. This is called **misprediction**.

When misprediction occurs, you will need to adjust the Client state to match the server state in one way or another. This is called **server reconciliation**.

There are many possible approaches to server reconciliation and coherence doesn't favor one over another. The simplest method is to snap the Client state to the server state once a misprediction is detected. Another method is to continuously blend from Client state to server state.

Misprediction detection and reconciliation can be implemented in a binding's `OnNetworkSampleReceived` event callback. This event is called every time new network data arrives, so we can test the incoming data to see if it matches with our local Client state.

```csharp
private void Awake()
{
    var positionBinding = GetComponent<CoherenceSync>().Bindings.FirstOrDefault(c => c.Name == "position");
    positionBinding.OnNetworkSampleReceived += DetectMisprediction;
}

private void DetectMisprediction(object sampleData, bool stopped, long simulationFrame)
{
    const float MispredictionThreshold = 3;

    var networkPosition = (Vector3)sampleData;
    var distance = (networkPosition - transform.position).magnitude;

    if (distance > MispredictionThreshold)
    {
        transform.position = networkPosition;
    }
}
```

The **misprediction threshold** is a measure of how far the prediction is allowed to drift from the server state. Its value will depend on how fast your player is moving and how much divergence is acceptable in your particular game.

Remember that incoming sample data is delayed by the round-trip time to the server, so it will trail the currently predicted state by at least a few frames, depending on network latency. The `simulationFrame` parameter tells you the exact frame at which the sample was produced on the authoritative server.

{% hint style="info" %}
For better accuracy, incoming network samples should be compared to the predicted state at the corresponding simulation frame. This requires keeping a history buffer of predicted states in memory.
{% endhint %}

## Client as a Host

{% hint style="warning" %}
This feature is in the experimental phase.
{% endhint %}

A client-hosted session is an alternative way to use **CoherenceInput** in **Server Side With Client Input** mode that doesn't require a Simulator.

A Client that created a [Room](/2.3/manual/replication-server/rooms-and-worlds#rooms) can join as a Host of this Room. Just like a Simulator, the Host will take over the State Authority of the **CoherenceInput** objects while leaving the Input Authority in the hands of the Client that created those objects.

The difference between a Host and a Simulator is that the Host is still a standard client connection, which means it counts towards the Room's **client limit** and will show up as a client connection in the connection [list.](/2.3/manual/client-connections#3-create-a-client-connection-prefab)

### Usage

To connect as a Host all we have to do is call `CoherenceBridge.ConnectAsHost`:

```csharp
public async Task CreateRoomAndJoinAsHost(string region)
{
    // Wait until a player account has logged in to coherence Cloud.
    PlayerAccount playerAccount = await PlayerAccount.GetMainAsync();

    var roomServiceForRegion = playerAccount.Services.Rooms.GetRoomServiceForRegion(region);

    var roomData = await roomServiceForRegion.CreateRoomAsync(RoomCreationOptions.Default);
    var (roomEndpoint, isEndpointValid, validationErrorMessage) = RoomData.GetRoomEndpointData(roomData);

    if (!isEndpointValid)
    {
        throw new Exception($"Invalid room endpoint: {validationErrorMessage}");
    }

    // Connect to the room as a host.
    if (CoherenceBridgeStore.TryGetBridge(gameObject.scene, out var bridge))
    {
        bridge.onConnected.AddListener(OnConnected);
        bridge.ConnectAsHost(roomEndpoint);

        void OnConnected(CoherenceBridge bridge) => Debug.Log($"Connected! IsHost: {bridge.IsSimulatorOrHost}");
    }
}
```

## Interaction with LiveQueries

[CoherenceLiveQuery](/2.3/manual/components/coherence-live-query) is a component that can be used to constrain the area of entities that are replicated on the client.

When using a LiveQuery, The [Replication Server](/2.3/manual/replication-server) filters out networked objects that are outside the range of the defined range. This can be useful as an optimization, and a security mechanism, to ensure clients can't exploit the system by inspecting the incoming network traffic, outside of what they are allowed to see. However the question arises: what if the player exploits by moving the position of the LiveQuery?

When a query component is part of a [CoherenceSync](/2.3/manual/components/coherence-sync) that is set to *Server Side With Client Inputs*, the query visibility will be applied to the client that owns Input Authority (i.e., the Client) while the component's state remains in control of the State Authority (i.e., the [Simulator](/2.3/manual/simulation-server))**.**

This prevents clients from viewing other parts of the world by simply manipulating the extents or the position of the LiveQuery.

{% hint style="info" %}
See [CoherenceLiveQuery](/2.3/manual/components/coherence-live-query) and [Area of interest](/2.3/manual/optimization/areas-of-interest) for more information on how to use queries.
{% endhint %}


# Lifetime

### Session-based vs persistent

When a Client connects, the traditional approach is that all Entities originating on this Client are session-based. This means that when the Client disconnects, they will disappear from the network for all players.

When entities are configured as persistent, they will remain on the Replication Server instead, even when the Client or Simulator that created or last simulated it is gone.

Common examples of persistent objects could be:

* A door anyone can open, close or lock
* User-generated or user-configured objects left in the world to be found by others
* Game progress objects (e.g. in PvE games)
* Voice or video messages left by users
* NPC's wandering around the world using an AI logic
* Player characters on "auto pilot" that continue affecting the world when the player is offline
* And many, many more

A persistent object that is not *adopted* by any Client is called *an orphan.* Orphans can be configured to be auto-adopted by Clients or Simulators on a FCFS basis.

<figure><img src="/files/ww4nawRIvRKoOse6Whbo" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Persistence in this context refers to **session persistence only**. This means that players can leave the game, come back, and still find persistent objects and entities, as long as the World or Room is still alive.

However, as soon as a World or Room are being shut down, or the Replication Server is restarted, the state is lost.
{% endhint %}

{% hint style="warning" %}
Currently, the maximum number of persistent objects supported by the Replication Server is **32000**.
{% endhint %}


# Uniqueness

Uniqueness is about naming entities and guaranteeing that a named entity can only exist once. This name is referred to as **Unique ID**.

To start using uniqueness, set CoherenceSync's Uniqueness setting to `No Duplicates`:

<figure><img src="/files/djoimPSU0tjFWfUeElnt" alt=""><figcaption><p>CoherenceSync Inspector</p></figcaption></figure>

### Unique ID

The ID or name of the entity. Use any name you might help you recognize it over the network, for example: `game manager`, `boss, spawner`, `chest 1`, ...

When Manual Unique ID is left empty, Prefab Instance Unique ID will be used instead. The latter is assigned automatically (for prefab instances), to tell apart different instances on the scene easily. This is handy when your scene has a handful of the entities \[that come from the same Prefab] around.

{% hint style="info" %}
In **coherence**, the concepts of **Authority**, **Persistence** and **Uniqueness** often go hand-in-hand. For example, uniqueness can be useful to keep track of persistent objects. Despite this, all three can also function on their own.
{% endhint %}

### Advanced Uniqueness Options

#### Replacement Strategy

Replacement occurs when there's an attempt to create a named entity that already exists. For example, you have `player` in your scene, and you instantiate another `player`.

By default, a Replace strategy is applied. This strategy makes sure the actual GameObject is kept, but the underlying linked entity is updated. This way, Unity Object references are not lost.

However, there's scenarios where you might want to trigger an actual Destroy operation when this happens - for such cases, the Destroy strategy can be used.


# Instantiation and destruction

If you instantiate a [Networked Prefab](#user-content-fn-1)[^1] while the game is running, it **automatically instantiates** on all connected clients. You don't need to do anything else to make it happen.

However some rules apply, so read on to understand more about the process.

### How do I specify a Prefab to spawn for the player?

It is important to understand that coherence has no concept of a "player Prefab" that maps 1:1 with each Client. Clients can control only one network entity, multiple, or none at all.

Clients can also trade authority over them at runtime. For example, a Client might initially have authority over a character, which can then move to another Client during gameplay.

It's **up to you** to decide what constitutes a "player Prefab": you can instantiate one before connecting, right after connection, or at any point during the simulation. You can even just leave it in the scene, and let each player bring a copy of that into the simulation (in this case, make sure the Prefab is not set to be [unique](/2.3/manual/networking-state-changes/uniqueness)!).

Finally, if you come from other networking frameworks, you might expect a player Prefab to be instantiated by the network manager (in coherence, the [CoherenceBridge](/2.3/manual/components/coherence-bridge)), but that is not the case. Like all other network entities, it can be **instantiated by any script**.

{% hint style="info" %}
**Identifying Clients**

You do have the ability to assign a Prefab to each client: the [ClientConnection Prefab](/2.3/manual/client-connections#clientconnection-objects). This lives and dies with the client's connection, and you can use it to hold important data related to that Client. You can assign it in the Inspector of the [CoherenceBridge](/2.3/manual/components/coherence-bridge).

ClientConnection Prefabs are **optional**.
{% endhint %}

## Instantiating entities

You can instantiate a networked Prefab in the following ways:

* Use `GameObject.Instantiate()`, and provide a reference to the Networked Prefab.
* Have an instance of the Networked Prefab in a scene (can drop it on the scene while in Play Mode too).

In these cases, the Prefab will be immediately instantiated on all other connected clients and Simulators.

Just ensure to include a CoherenceSync component on the Prefab, and that netcode is [baked](/2.3/manual/baking-and-code-generation) correctly.

### Who gets authority?

Whoever instantiates a Prefab gets full [authority](/2.3/manual/networking-state-changes/authority) over it. All other clients will see it as remote.

{% hint style="info" %}
The value of the **Simulate In** property on the CoherenceSync can modify this behaviour. Read more about [authority models](/2.3/manual/networking-state-changes/authority/authority-transfer).
{% endhint %}

### Instantiate objects for other clients

You cannot directly instantiate an entity owned by another Client. The Client that instantiates a Prefab automatically has authority over it.

However, you can transfer authority immediately after instantiation. In code:

<pre class="language-csharp"><code class="lang-csharp">// Instantiates a Prefab and immediately gives authority away
public void SpawnAndTransfer(GameObject prefab, ClientID recipientID)
{
<strong>    var newGameObject = Instantiate(prefab);
</strong>    var sync = newGameObject.GetComponent&#x3C;CoherenceSync>();
    sync.TransferAuthority(recipientID);
}
</code></pre>

(to get other clients' IDs you need to have [ClientConnections](/2.3/manual/client-connections) enabled)

{% hint style="success" %}
This is a perfectly valid strategy to have a Simulator spawn player characters for connected Clients.
{% endhint %}

## Destroying entities

To destroy a networked Prefab, simply invoke `GameObject.Destroy()` on it. coherence will **automatically destroy all remote copies**.

Keep in mind is that only whoever has State authority over it can destroy an entity. If someone else does it, they will get a warning in the console.

### Destroying other player's entities

Clients cannot directly destroy entities they don't have authority over. Instead, you may:

* Send a [Network Command](/2.3/manual/networking-state-changes/commands) to **ask the owner to destroy it**. In code:

```csharp
public void DestroyNetworkEntity(GameObject target)
{
    var sync = target.GetComponent<CoherenceSync>();

    if (sync.HasStateAuthority)
    {
        // If we have authority, no need to send a command
        Destroy(target);
    }
    else
    {
        sync.SendCommand<DestroyNetworkEntityExample>(
            nameof(RemoveObject),
            MessageTarget.AuthorityOnly);
    }
}

// The command invoked on the receiving end
[Command]
public void RemoveObject()
{
    Destroy(this.gameObject);
}
```

* **Take authority over the entity first**, then destroy it locally. This is slightly slower as it implies a full roundtrip (request > response > destruction), but it's a viable option if the requester needs to verify whether the entity can be destroyed at all. You can implement the conditions under which the other client will [approve or deny the request](/2.3/manual/networking-state-changes/authority/authority-transfer#requesting-authority-in-code). In code:

```csharp
private void RequestDestroy(GameObject target)
{
    var sync = target.GetComponent<CoherenceSync>();

    if (sync.HasStateAuthority)
    {
        Destroy(target);
    }
    else
    {
        // Listen to authority transfer
        sync.OnStateAuthority.AddListener(() => Destroy(target));
        sync.RequestAuthority(AuthorityType.Full);
    }
}
```

Note that we're assuming that the request above always succeeds, and we're not implementing any approval/denial code for the sake of simplicity.

## Customise instantiation and destruction

In coherence, you can take full control of how network entities are instantiated.

A typical use for custom instantiation is streaming assets in with the [**Addressables package**](https://docs.unity3d.com/Packages/com.unity.addressables@latest), which coherence is fully integrated with. Another typical use case is [object pooling](#object-pooling).

To use custom instantiation you can't just hard reference the Prefab and invoke `Instantiate()` or `Destroy()` as described above. Instead, you have to [use its CoherenceSyncConfig](/2.3/manual/networking-state-changes/asset-management/using-coherencesyncconfig-to-instantiate-gameobjects) to let the chosen instantiator script take over and perform custom operations.

## Object pooling

We natively support object pooling, so that newly requested entities don't just get created from scratch, but they are taken from a pre-existing pool.

#### How to use object pooling

In the CoherenceSync component inspector, you will find an option called **Instantiate Via**.

Select the option called *Pool*, and define the initial and max size of the pool:

<figure><img src="/files/tQHAqXcK6vhXceSCefBK" alt="" width="563"><figcaption><p>A CoherenceSync for which the Pool instantiator has been selected</p></figcaption></figure>

When the game starts, coherence will automatically create a pool of disabled instances of this Prefab in the DontDestroyOnLoad scene. It will then activate these for new **remote entities** that use this Prefab that other clients created.

If you want to take from the same pooling system to instantiate your own **local/authoritative entities**, you can do so by using the [CoherenceSyncConfig asset](/2.3/manual/networking-state-changes/asset-management#coherencesyncconfig-assets) corresponding to your Prefab. If you reference this asset, you will be able to [instantiate and destroy entities by using its API](/2.3/manual/networking-state-changes/asset-management/using-coherencesyncconfig-to-instantiate-gameobjects): these methods will use the underlying pool implementation to do so.

When remote entities are removed or go out of a [LiveQuery](/2.3/manual/optimization/areas-of-interest), they will be automatically deactivated and move back into the pool.

#### Use your pre-existing object pooling system

If you already have a pooling system in place (even a third-party asset!) and you would like remote objects to leverage it, you can hook your own pool into a custom instantiator using the `INetworkObjectInstantiator` interface. This is described in the [Instantiate Via page](/2.3/manual/networking-state-changes/asset-management/instantiate-via#creating-your-own-instantiator).

[^1]: A Prefab that has a CoherenceSync component.


# Hierarchies

Networking variables and methods within a Networked Prefab transform hierarchy

If a synced Prefab has a hierarchy, you can synchronize variables, methods and component actions for any of the child GameObjects within its hierarchy.

{% hint style="warning" %}
Note: on this page we cover children GameObjects or nested Prefabs that **don't** have their own`CoherenceSync`. If a child object **does have** a `CoherenceSync` of their own, they become an independent network entity. For that, see the [Parenting section](/2.3/manual/networking-state-changes/parenting).
{% endhint %}

When the *Configure* window is open it will show the variables, methods and component actions available for synchronization for your currently selected GameObject.

First, make sure to be editing the Prefab in Prefab Mode:

<figure><img src="/files/jOFhxzOC40lzJQM8P6Hs" alt=""><figcaption><p>Configuration window showing <em>Open Prefab Asset</em>.</p></figcaption></figure>

Once in Prefab Mode and with the *Configure* window open, shift the selection to 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 on the child GameObject:

<figure><img src="/files/hA5hPCBSbjZRE5bwKfXS" alt=""><figcaption><p>A Prefab Stage showing Player, and configuring a child in the hierarchy.</p></figcaption></figure>

That's it!

Syncing properties, methods and component actions on child GameObjects doesn't require any different flow than what you usually do for the root object. They all get collected and networked as part of one single network entity.

After your changes to GameObject, don't forget to [Bake](/2.3/manual/baking-and-code-generation) again to rebuild the netcode for the entity.

{% hint style="warning" %}
Make sure to not destroy child GameObjects that have synced properties, or you will receive a warning in the Console. To destroy a synced object, always remove the root.

(you can totally destroy children that don't have any synced property)
{% endhint %}


# Parenting

How to parent Networked Prefabs to each other

Out of the box, **coherence** offers several options to handle parenting of networked entities. While some workflows are automatic, others require a specific component to be added.

Generally there is a distinction if the parenting happens at **runtime** vs. **edit time**, and whether the two entities are **direct** parent-child, or have a **complex hierarchy**. See below for each case.

**At runtime:**

* [CoherenceSyncs as a direct child](/2.3/manual/networking-state-changes/parenting/direct-children): when you create a parent-child relationship of `CoherenceSync` objects at runtime.
* [Deeply-nested CoherenceSyncs](/2.3/manual/networking-state-changes/parenting/deeply-nested-entities): when you create a complex parent-child relationship of `CoherenceSync` objects at runtime.

**At edit time:**

* [Nesting connected Prefabs assets](/2.3/manual/networking-state-changes/parenting/nesting-prefabs-at-edit-time): the developer prepares several connected Prefabs and nests them one to another before entering Play Mode. This covers both Prefabs in the scene and in the assets.

When preparing a CoherenceSync Prefab for use as a child object it is important to always configure the bindings so that position, rotation, and scale are bound. This will ensure that the proper transform state of the entity is maintained when it is parented to another CoherenceSync object.

<figure><img src="/files/6VGnr2T6V1bmOOEFkJFV" alt=""><figcaption><p>Make sure the child entity is prepared for parenting to another CoherenceSync entity</p></figcaption></figure>

{% hint style="info" %}
Try it out in our[ First Steps](https://coherence.io/games/coherence/first-steps-tutorial) interactive demo!\
Don't forget to also look at the [explanations](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/4-parenting-entities).
{% endhint %}


# Direct-children CoherenceSyncs

CoherenceSync direct parent-child relationships at runtime

Objects with the `CoherenceSync` component can be connected at runtime to other objects with a `CoherenceSync` component to form a direct parent-child relationship.

For example, an item of cargo can be parented to a vehicle, so that they move together when the vehicle is in motion.

Keep in mind that on this page we deal with **direct** parenting of two `CoherenceSync` GameObjects. If it's not practical to parent a network entity directly to the root of another, see instead how to [deeply nest CoherenceSyncs](/2.3/manual/networking-state-changes/parenting/deeply-nested-entities).

{% hint style="info" %}
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.
{% endhint %}

{% hint style="warning" %}
A child object will only be visible in a LiveQuery if its parent is within the query's boundaries.
{% endhint %}

## Implementation

Parenting network entities directly **doesn't require any extra work**. Any parenting code (i.e. Unity's own `transform.SetParent()` will work out of the box, without any need for additional action.

You can add and remove parent-child relationships at runtime – even from the Unity editor, by drag-and-drop.

### Effect on coherence LODs

If the child object is using LODs, it will base its distance calculations on the world position of its parent. For more info, see the [Level of detail](/2.3/manual/optimization/level-of-detail-lod#using-lods-with-connected-entities) documentation.

### Handling parent destruction

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, under *Advanced Settings*:

<figure><img src="/files/pKvz49co7aekHllogFWl" alt=""><figcaption></figcaption></figure>

When *Preserve Children* is enabled, if the authority destroys or disables the parent entity, child entities get unparented instead of being destroyed together with the parent. Those children will now reside at the root of the Scene hierarchy.

{% hint style="info" %}
For an example of direct child `CoherenceSync` components parenting and unparenting at runtime, check out the **First Steps** sample project, specifically [lesson 4](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/4-parenting-entities).

<img src="/files/W1OVVqcNDjRB6WcnTkfC" alt="" data-size="original">
{% endhint %}


# Deeply-nested CoherenceSyncs

Creating complex hierarchies of CoherenceSyncs at runtime

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 specific component.

{% hint style="info" %}
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*
{% endhint %}

### Implementation

To prepare the child Prefab that you want to parent at runtime, add the `CoherenceNode` component to it (in addition to its `CoherenceSync`). In the example above, that would be the flashlight you want your player to be able to pick up. No additional changes are required.

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 would work).

![A CoherenceNode before pressing Play](/files/yJrGJ2sX7rOZ798ThX70)

You **don't** need to input any value in the fields of the `CoherenceNode`. They are used at runtime, by coherence, automatically.

To recap, for deep-nesting network entities to work, you need two things:

1. The parent: a Prefab with `CoherenceSync` that has some hierarchy of child transforms (these child transforms are not networked entities themselves).
2. The child: another connected Prefab with `CoherenceSync` and `CoherenceNode`.

### Ensuring hierarchies are in sync

One important constraint for using `CoherenceNode` is that the **hierarchies have to be identical on all Clients**.

{% hint style="success" %}
Example: if on Client A an object is parented to *Player > Shoulder > Arm > Hand*, the hierarchy on Client B needs to be exactly: *Player > Shoulder > Arm > Hand*.

Removing or moving an intermediate child (such as *Shoulder* or *Arm*) would lead to undesirable results, and desynchronisation.
{% endhint %}

**Position and rotation**

Similarly to the above, intermediate children objects need to have **the same position and rotation on all Clients**. If not, that would lead to desync because the parented entity doesn't track the position of its parent object(s).

If you plan to move these intermediate children, then we suggest to sync the position and/or rotation of those objects as part of the containing Prefab.

{% hint style="success" %}
Following the previous example, if an object is parented to *Player > Shoulder > Arm > Hand*, you might want to mark the position and rotation of *Shoulder*, *Arm* and *Hand* as synce&#x64;*,* as part of the prefab *Player*.

This way if any of them moves, the movement will be replicated correctly on all clients, and the object parented to *Hand* will also look correct.
{% endhint %}

Keep in mind that there is no penalty for synching positions of objects that never or rarely move, because the position is not synched every frame if it hasn't changed.

{% hint style="info" %}
For an example of a `CoherenceSync` parenting and unparenting at runtime in a deep hierarchy, check out the **First Steps** sample project, [lesson 5](/2.3/getting-started/samples-and-tutorials/first-steps-tutorial/5-complex-hierarchies).

<img src="/files/TpCVY5RBJTtMHhnjgxgZ" alt="" data-size="original">
{% endhint %}


# Nesting prefabs at edit time

Preparing nested connected Prefabs at edit time

coherence supports all Prefab-related Unity workflows, and nesting is one of them. It can make a lot of sense to prepare multiple networked Prefabs, parent them to each other, and either place them in the scene, or save them as a complex Prefab, ready to be instantiated. This page covers these cases.

### Nested Prefabs for instantiation

When preparing a networked Prefab that contains another networked Prefab, one extra component is needed to allow **coherence** to sync the whole hierarchy: `PrefabSyncGroup`.

For instance, let's suppose we have a vehicle in an RTS that can carry cargo, and it comes with cargo pre-loaded when it's instantiated:

<figure><img src="/files/2YDNf2MAnsX187UstwUl" alt="" width="563"><figcaption></figcaption></figure>

In this example **Spacetruck** is a synced Prefab, with 4 instances of the synced Prefab **Cargo** nested within. To make this work, we add a `PrefabSyncedGroup` to the root:

<figure><img src="/files/EhDTi1kmJ3t3mStNPk80" alt="" width="563"><figcaption><p>The PrefabSyncGroup component</p></figcaption></figure>

The component keeps track of child Prefabs that are also synced Prefabs. Now, whenever **Spacetruck** is instantiated, `PrefabSyncGroup` makes sure to take 4 instances of **Cargo** and link the Prefab instances to the correct network entities.

{% hint style="warning" %}
Please note that if the nested Prefabs are more than one level under the root object, you still need to add a `CoherenceNode` component to the child ones (in the example above, **Cargo**), to enable [deep nesting at runtime](/2.3/manual/networking-state-changes/parenting/deeply-nested-entities).
{% endhint %}

So to recap:

* The outermost Prefab needs `CoherenceSync` and `PrefabSyncGroup`.
* The child Prefabs need `CoherenceSync` and, optionally, `CoherenceNode`.

### Nested Prefabs pre-placed in a Unity scene

When dealing with synced Prefabs that are hand-placed in the scene before connecting, such as level design elements like interactive doors, you need to ensure that they are seen as "unique". This is also covered in the [Uniqueness page](/2.3/manual/networking-state-changes/uniqueness), but it's worth talking about it in the context of nested synced Prefabs.

When preparing such a Prefab, you need to set the *Uniqueness* property to *No Duplicates*. This ensures that, once multiple Clients connect and open the same scene, the synced Prefabs contained within are not spawned on the network multiple times.

Let's suppose we have a networked Prefab that represents a structure in an RTS (a **LandingPad**) that can be pre-placed in the scene. This structure also contains a networked vehicle Prefab (a **Lander**). This Prefab is synced as an independent network entity because at runtime it can detach, change ownership, be destroyed, etc.

To achieve this, all we need to do is ensure that both Prefabs are set to be **unique**. When we drag-and-drop the **LandingPad** Prefab into the scene, **coherence** automatically assigns a randomly-generated *Prefab Instance Unique ID* as an override. This number identifies these particular instances of these two Prefabs in the scene.

<figure><img src="/files/8Lk5OXKXsRtWHn1rFB4y" alt=""><figcaption><p>Each instance received its own unique ID</p></figcaption></figure>

With this setting, we don't need to do anything else for these compound Prefabs to work.

{% hint style="warning" %}
Like for runtime-instantiated Prefabs, keep in mind that if the **Lander** is nested[ 2 or more levels deep](/2.3/manual/networking-state-changes/parenting/deeply-nested-entities) in the hierarchy, it will also need a `CoherenceNode` component.
{% endhint %}

{% hint style="success" %}
If you plan to also instantiate this Prefab at runtime, you can add a `PrefabSyncGroup` to the root as described in the [previous section](#nested-prefabs-for-instantiation). This makes the Prefab work when instantiated at runtime, while the uniqueness takes care of copies in the scene.
{% endhint %}

To recap:

* The outermost Prefab needs its *Uniqueness* set to *No Duplicates*. Optionally, you can add `PrefabSyncGroup` to enable runtime-instantiation.
* Any child Prefab also needs its *Uniqueness* set to *No Duplicates*. It also needs a `CoherenceNode` if it's parented deep in the hierarchy.

#### Unique IDs on already-placed Prefabs

An important thing to keep in mind when working with compound Prefabs in the scene: when you add a new nested synced Prefab to an existing one that has **already been placed in the scene** a few times, the *Prefab Instance Unique ID* for these instances will initially be the same.

For this reason, once you play the game, you might see all children disappear (except one). That is normal: **coherence** thinks that all these network entities are the same, because they have the same uniqueness ID.

You need to ensure that these new children have an overriden and unique ID **on each instance** in the scene. To do so, click on the button next to the *Prefab Instance Unique ID* for each child that needs it:

<figure><img src="/files/OnaBluqR3KVMsbUno0To" alt=""><figcaption><p>Press the button to generate a new unique ID for this instance</p></figcaption></figure>


# Animators

{% hint style="info" %}
**coherence** only replicates animation parameters, not state. Latency can create scenarios where different Clients reproduce different animations. Take this into account when working with Animator Controllers that require precise timings.
{% endhint %}

Unity Animator's parameters are bindable out of the box, **with the exception of triggers**.

![Guard, Walk, MovX and MovY parameters available on CoherenceSync as variables](/files/AjwGQLxq73yla8OoKpkT)

### Multiple AnimatorControllers

While **coherence** doesn't officially support working with multiple AnimatorControllers, there's a way to work around it. As long as the parameters you want to network are shared among the AnimatorControllers you want to use, they will get networked. Parameters need to have the same type and name. Using the example above, any AnimatorController featuring a Boolean *Walk* parameter is compatible, and can be switched.

### Triggers

Triggers can be invoked over the network using [commands](/2.3/manual/networking-state-changes/commands). Here's an example where we inform networked Clients that we have played a jump animation:

```csharp
using UnityEngine;
using Coherence;
using Coherence.Toolkit;

public class JumpController : MonoBehaviour
{
    CoherenceSync coherenceSync;
    Animator animator;

    void Awake()
    {
        coherenceSync = GetComponent<CoherenceSync>();
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        if (!coherenceSync.HasInputAuthority)
        {
            return;
        }

        if (Input.GetKeyDown(KeyCode.Space))
        {
            MakePlayerJump();
        }
    }

    void MakePlayerJump()
    {
        coherenceSync.SendCommand<JumpController>(nameof(PlayJumpAnimation), MessageTarget.All, coherenceSync);
    }

    // bind to this method via the Bindings window
    public void PlayJumpAnimation(CoherenceSync jumpSync)
    {
        animator.SetTrigger("Jump");
    }
}
```

Now, bind the `PlayJumpAnimator` method as a [command](/2.3/manual/networking-state-changes/commands).

![PlayJumpAnimation command](/files/929bNiYSg5QYeaxDaCjb)


# Rigidbodies

### Overview

Supporting Unity physics in a network environment requires managing the state of rigid bodies on replicated Prefabs. Generally, if a Prefab using CoherenceSync has a *Rigidbody* or *Rigidbody2D* component, the replicated instances of the Prefab should have the body set to kinematic so that they do not simulate in the physics step on non-authoritative clients. There is a convenient configuration for this in the CoherenceSync configuration components tab.

<figure><img src="/files/8q1g7PUzJkNuwNWMnOnS" alt=""><figcaption><p>Set the state of replicated Rigidbody components to kinematic</p></figcaption></figure>

For most purposes, this is all that is required to have physically simulated entities correctly replicated on Clients. However, only the transform of the rigid body is actually replicated. For additional physical state replication a more advanced setup is required.

### Advanced Rigid Body support

The CoherenceSync component supports three modes for replication of Unity rigid bodies:

* **Direct** - the default mode used for basic replication of the transform of the Unity GameObject with a rigid body component. When a rigid body is detected, the position and rotation of the GameObject are provided by and assigned to the rigid body's position and rotation directly and Unity updates the GameObject transform after the physics step.
* **Interpolated** - similar to Direct mode, except the update to the rigid body position and rotation are applied using [MovePosition](https://docs.unity3d.com/ScriptReference/Rigidbody.MovePosition.html) and [MoveRotation](https://docs.unity3d.com/ScriptReference/Rigidbody.MoveRotation.html) which allows the Unity physics system to calculate rigid body state such as linear and angular velocity on Clients with replicated Entities.

{% hint style="info" %}
For best behavior, it is recommended that the interpolation timing use only **FixedUpdate**.\
See the article on [Interpolation](/2.3/manual/networking-state-changes/interpolation).
{% endhint %}

* **Manual** - disables automatic update of position and rotation of CoherenceSync Prefabs with rigid bodies and enables the use of callbacks, allowing custom implementation of how position and rotation updates are applied. The callbacks are *OnRigidbody2DPositionUpdate*, *OnRigidbody3DPositionUpdate*, *OnRigidbody2DRotationUpdate*, and *OnRigidbody3DRotationUpdate*.

<figure><img src="/files/1d7O9aFNxTolaKq3uNyv" alt=""><figcaption><p>Setting Rigidbody Update Mode to Interpolated for advanced physics setup.</p></figcaption></figure>


# Entity references

coherence is able to network references to other instances of Networked Prefabs.&#x20;

To do so, network any variables or methods using `GameObject` or any `Component` type:

<figure><img src="/files/E3C84mWd6jmWOEPee9mh" alt=""><figcaption></figcaption></figure>

### Limitations

It's important to know about the situations when a Networked Prefab reference might become null, even though it seems like it should have a value:

* A client might not have the referenced entity in its CoherenceLiveQuery. A local reference can only be valid if there's an actual Entity instance to reference. If this becomes a problem, consider switching to using the [CoherenceNode](/2.3/manual/networking-state-changes/parenting/deeply-nested-entities) component or [Parent-Child relationships](/2.3/manual/networking-state-changes/parenting/direct-children) of prefabs, which ensures that that Entity stays part of the query.
* The owner of the Entity reference might sync the reference to the Replication Server before syncing the referenced Entity. This will lead to the Replication Server storing a null reference. If possible, try setting the Entity references during gameplay when the referenced Entities have already existed for a while.
* **Cyclic references** are **undefined behavior** for now. Therefore multiple entities created on the same Client that reference each other might never get synced properly. This is also holds true for references that exist through intermediate entities (A has reference to B has reference to C has reference A - cyclic).

In any case, it's important to use a defensive coding style when working with Entity references. Make sure that your code can handle missing Entities and nulls in a graceful way.


# Interpolation

### Overview

For an object to appear to move smoothly on the screen, it must be rendered at a high rate, usually 60 frames per second or more. However, depending on the settings in your project, and the conditions of your internet connection, data may not always arrive at a smooth 60 frames per second across the network. This is completely okay, but in order to make state changes appear smooth on the Client, we use interpolation.

**Interpolation** is a type of estimation, a method of constructing new data points within the range of a discrete set of known data points.

When you select a variable to replicate in the *Configure* window, it is automatically assigned a default interpolation setting. The default settings are usually good to get started, but you can modify or create your own interpolation settings that better fit your specific needs.

### Configuring interpolation settings

In the *Configure* window, each binding displays its interpolation settings next to it.

<figure><img src="/files/ReMGZmOnEmTov83MVl85" alt=""><figcaption></figcaption></figure>

Built-in interpolation settings for position and rotation are provided out-of-the-box, but you are free to create your own and use them instead.

<figure><img src="/files/pfmzdg2iFYxYlKUtWGXg" alt=""><figcaption><p>Creating a new Interpolation Settings object.</p></figcaption></figure>

{% hint style="info" %}
You can also create an interpolation settings asset: *Assets > Create > coherence > Interpolation Settings*
{% endhint %}

### Interpolation types

**Linear interpolation** blends values by moving along straight lines from sample to sample. This makes the networked object move in a zig-zag pattern, but this is usually not noticeable when sampled at a sufficient rate and with some additional smoothing applied (see section [*Other settings*](#other-settings) *>* [*Smoothing*](#other-settings) below).

**Spline interpolation** blends between samples using the Catmull-Rom spline method which gives a smoother movement than linear interpolation without any sharp corners, at the cost of increased latency (see: *Latency* below). Spline interpolation requires at least 4 samples to produce good results.

If interpolation type is set to **None**, the value will simply snap to the most recent sample without any blending. This is recommended for binding types that have no obvious blending methods, e.g., string, byte array and object references.

You could also implement your own interpolation type (see: [*Custom Interpolators*](#custom-interpolators) below).

### Latency

Interpolation will add some additional latency to synced bindings. That's because incoming network samples must first be put in a buffer that is then used to calculate the interpolated value.

The amount of latency depends on the binding's sample rate and interpolation type. The lower the sample rate, the higher the latency.

*Linear Interpolation* requires a headroom of one sample while *Spline Interpolation* requires two samples. If interpolation type is set to *None*, there is no additional latency added, and samples will be rendered as soon as they arrive over the network.

{% hint style="info" %}
Example: A Prefab that uses *Spline Interpolation* for its position binding with a sample rate of 30 Hz and network latency of 100 ms will appear to be 2\*1/30+0.100 = 0.16 s behind the local time.
{% endhint %}

Since a Prefab can define separate interpolation types and sample rates for its different bindings, it is possible that not all bindings share the same latency. If, for example, position and rotation are interpolated with different latencies, the position and rotation of a vehicle might not match on the remote object.

### Other Settings

There are a few settings you can tweak:

* **Smoothing**
  * *Smooth Time*: additional smoothing can be applied (using [`SmoothDamp`](https://docs.unity3d.com/ScriptReference/Mathf.SmoothDamp.html)) to clear out any jerky movement after regular interpolation has been performed.
  * *Max Smoothing Speed*: the maximum speed at which the value can change, unless teleporting.
* **Latency**
  * *Network Latency Factor*: fudge factor applied to the network latency. A factor of 1 means adapting to network latency with no margin, so the incoming sample must arrive at its exact predicted time to prevent the buffer from becoming stale. In general, a factor of 1.1 is recommended to prevent network fluctuations from causing dead reckoning due to latency peaks.
  * *Network Latency Cooldown*: when network latency decreases, wait this amount of time (in seconds) before recalculating network latency. This prevents network fluctuations from causing dead reckoning due to latency valleys.
  * *Additional Latency*: increases latency by a fixed amount (in seconds) to add an additional margin for the sample buffer.
* **Overshooting**
  * *Max*: how far into the dead reckoning to venture when the time fraction exceeds 100%, as a percentage of the sample rate.
  * *Retraction*: how fast to pull back to 100% when overshooting the allowed dead reckoning maximum (in seconds)
* **Teleport Distance**: if two consecutive samples are further apart than this, the value will teleport or snap to the new sample immediately without interpolating or smoothing in between.
* **Stale Factor**: defines when to insert a *virtual sample* in case of a longer time gap between the samples. High stale factor puts the virtual sample close to first sample leading to a smooth transition between two distant samples. This is suitable for parameters that do not change rapidly - the position of a big ship for example. Low stale factor places the virtual sample near the second sample resulting in initial lack of change in value during interpolation followed by a quick transition to the second sample. This is best suited for parameters that can change rapidly, e.g. position of a player.

{% hint style="info" %}
**Dead reckoning** is a form of replicated computing so that everyone participating in a game winds up simulating all the entities (typically vehicles) in the game, albeit at a coarse level of fidelity.

The basic notion of dead reckoning is an agreement in advance on a set of algorithms that can be used by all player nodes to extrapolate the behavior of entities in the game, and an agreement on how far reality should be allowed to get from these extrapolation algorithms before a correction is issued.
{% endhint %}

{% hint style="info" %}
**Interpolation settings** can be tweaked in **Play mode** where you can see the result on the screen immediately, but the changes you make will be reverted again once you exit Play mode. This is because - in Play mode - a copy of the interpolation settings is created.

Remember that interpolation only happens on remote objects, so you need to select a remote object to experiment with interpolation settings in Play mode.
{% endhint %}

You can change these settings at runtime via the *Configure* window (editor) or by accessing the binding and changing the interpolation settings yourself:

```csharp
if (coherenceSync.TryGetBinding(typeof(Transform), "position", out Binding binding))
{
    // change your interpolation settings at runtime
    binding.interpolationSettings = someSettings;
}
```

### Custom interpolators

The Linear and Spline interpolators that are provided by coherence are sufficient for most common use cases, but you can also implement your own interpolation algorithm by sub-classing `Interpolator`.

You can choose to override one or more of the base methods depending on which type or types of values you want to support. The method signatures usually take two adjacent samples and a fractional value (from 0 to 1) to blend between them. There are also method signatures that provide four samples, which is useful for the Catmull-Rom spline interpolation.

Here's an example of a custom interpolator that makes the remote object appear at an offset distance from the object's actual position.

```csharp
using System;
using Coherence.Interpolation;
using UnityEngine;

[Serializable]
public class InterpolatorWithOffset : Interpolator
{
    public Vector3 offset;
    public override int NumberOfSamplesToStayBehind => 1;

    public override Vector3 InterpolateVector3(Vector3 value1, Vector3 value2, float t)
    {
        var interpolatedValue = Vector3.Lerp(value1, value2, t);
        return interpolatedValue + offset;
    }
}
```

The **NumberOfSamplesToStayBehind** property controls the internal latency.

{% hint style="info" %}
Catmull-Rom splines require four samples to blend between, so its **NumberOfSamplesToStayBehind** property must be set to 2.
{% endhint %}

<figure><img src="/files/nm7yZGhNrL7MHAEKqCqI" alt=""><figcaption><p>The new Interpolator is available from the Interpolator Type dropdown with the offset field as a configurable parameter.</p></figcaption></figure>

### Interpolation timing

By default, each binding is interpolated on every [Update](https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html) call. This can be changed using the *Interpolate On* property on the [CoherenceSync](/2.3/manual/components/coherence-sync) under *Advanced Settings*. Possible values are:

* ***Update*** / ***LateUpdate*** / ***FixedUpdate*** - bindings will be updated with interpolated values on every [Update](https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html) / [LateUpdate](https://docs.unity3d.com/ScriptReference/MonoBehaviour.LateUpdate.html) / [FixedUpdate](https://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html) call
* ***Combination*** - you can combine any of the above, so that bindings are updated in more than one Unity callback
* ***Nothing*** - bindings will completely stop receiving new values because interpolation is fully disabled

{% hint style="info" %}
If you are using Rigidbody for movement of a GameObject, it is recommended to set *Interpolate On* to *FixedUpdate*. Also, to achieve completely smooth movement, [Rigidbody interpolation](https://docs.unity3d.com/ScriptReference/Rigidbody-interpolation.html) should be enabled and you should avoid setting the position of a GameObject directly using [Transform.position](https://docs.unity3d.com/ScriptReference/Transform-position.html) or [Rigidbody.position](https://docs.unity3d.com/ScriptReference/Rigidbody-position.html).
{% endhint %}

### Extrapolation

Extrapolation uses historical data to predict the future state of a binding. By predicting the state of other players before their network data actually arrives, network lag can be reduced or removed entirely. This will cause mispredictions that need to be corrected when the incoming network data does not match the predicted state.


# Big Data

Using fragmented channels to synchronize data that wouldn't usually fit in a packet.

Synchronizing entities with `byte[]` or `string` bindings, or sending commands with `byte[]` or `string` arguments allows you to sync large amounts of custom data. However, if an entity update, or a single command, is too large to fit inside a single packet (where default MTU is 1280 bytes), then the entity update or the command will never be synchronized. To solve this problem, and be able to sync data of practically any size, you can use **fragmented channels** for synchronization of entities or commands.

{% hint style="warning" %}
Because of the implementation nature of **fragmented channels**, sending large units of data over a **fragmented channel** will delay subsequent updates and commands (even of different entities) sent over the same **fragmented channel** until the original data is fully transferred.

For this reason, it is recommended to **separate latency-sensitive bindings** (such as player position) and big-data bindings by dividing them into different **CoherenceSyncs**.
{% endhint %}

Data synchronized over the **fragmented channels** shares the bandwidth with other data synchronized over other channels, but data sent over the **non-fragmented channels** has priority over fragmented data. Because the **bandwidth is** **shared** (not multiplied), very large data sent over a fragmented channel might be more delayed if you're already syncing a lot of data over other channels.

Watch out for the amount of data you're sending over the fragmented channel, since the default bandwidth is not very high. For example, at the default MTU of 1280 bytes and default send rate of 20Hz, the maximum data bandwidth is around 24KB/s (this is after taking part of the bandwidth for coherence headers). If no other data is sent over other channels, 100KB of data sent over a fragmented channel would take **over 4 seconds** to transfer to the Replication Server, and **4 more seconds** to transfer to other Clients, which brings the total latency to over 8 seconds for 100KB of data. But 5KB of data would be synced to other clients in under 500ms.

{% hint style="success" %}
The default MTU of 1280 bytes and send rate of 20Hz are used because they will work on most internet connections and are thus optimal for most games.
{% endhint %}

{% hint style="info" %}
Note that there is currently no reporting of transfer progress in the SDK. Because of that, when sending considerable amounts of data, the synchronization might feel stuck, but it's probably just taking time to transfer the data to the replication server and then to other clients.
{% endhint %}

In case you want to synchronize a considerable amount of data, which would be too slow using the default bandwidth, we recommend exploring other options such as [Cloud Storage](/2.3/hosting/coherence-cloud/game-services/cloud-storage), rather than increasing the MTU or send rate.

### Syncing big data over entity bindings

In the *Advanced Settings* of the **CoherenceSync,** you can change the **Synchronization Channel** of an entity. Choosing the **Fragmented** channel will synchronize creation, deletion, and all binding updates of the entity over the **Fragmented** channel, allowing you to sync data of any size.

{% hint style="info" %}
Note that the commands targeting that entity will still be sent over any channel. See the [commands section](#syncing-big-data-over-commands) for more details.
{% endhint %}

{% hint style="warning" %}
Use **Fragmented** channels only for entities that you are sure will have large data to synchronize, because, as noted before, those entities could potentially experience increased latency.
{% endhint %}

<figure><img src="/files/AcUzosAeBSPLYTTB7taa" alt=""><figcaption></figcaption></figure>

Since you don't want to send most bindings over the **fragmented channel**, the recommended way is to move bindings that contain big data to a separate **CoherenceSync,** and set only the new **CoherenceSync's Synchronization Channel** to **Fragmented**. One way of grouping those two entities together is by making the big data Prefab a child of the original Prefab using the [**PrefabSyncGroup**](/2.3/manual/networking-state-changes/parenting/nesting-prefabs-at-edit-time).

Note that the big data child object might not be replicated to the remote Clients at the same time as the parent object, so you need to be sure your game logic can handle a scenario where the big data child object is delayed.

### Syncing big data over commands

You can send commands over the **fragmented channel** to any entity, no matter if the entity is synchronized over the **Fragmented** or **Default** channel. To send a command over the **fragmented channel,** use the `SendCommandOverChannel(...)` and `SendCommandToChildrenOverChannel(...)` overloads, passing either **Fragmented** or **FragmentedOrdered** channel (for [ordered](/2.3/manual/networking-state-changes/commands#ordering-of-commands) commands) as an argument.

{% hint style="warning" %}
Use **Fragmented** channels only for commands that you are sure will have large data to send, because, as noted before, those commands could potentially experience increased latency.
{% endhint %}

```csharp
var data = new byte[5 * 1024]; // 5KB of data
sync.SendCommandOverChannel<Player>(
    nameof(Player.SendData),
    MessageTarget.AuthorityOnly,
    Channel.Fragmented,
    data);
```


# Asset management

In this section we cover in-depth how coherence handles loading networked Prefabs into memory, and how it instantiates them when a new remote entity appears on the network.

## CoherenceSyncConfig assets

Whenever you start synchronizing one of your Prefabs, either by adding the CoherenceSync component manually or clicking the **Sync with coherence** toggle in the Prefab Inspector, coherence will create a **CoherenceSyncConfig** ScriptableObject to track the existence of this entity, and add it to a [registry](#the-coherencesyncconfigregistry).

This object holds information on how a certain type of network entity is **loaded** and **instantiated**.

<figure><img src="/files/EZTlSD3peiBiD7z1ekIM" alt="" width="563"><figcaption><p>A CoherenceSyncConfig</p></figcaption></figure>

As a user, the two main changeable options here are [**Load via**](/2.3/manual/networking-state-changes/asset-management/load-via), and [**Instantiate via**](/2.3/manual/networking-state-changes/asset-management/instantiate-via).

There is a 1:1 correspondence between a networked Prefab and its CoherenceSyncConfig object, so you can also edit the related CoherenceSyncConfig directly from the Inspector of any CoherenceSync component:

<figure><img src="/files/tQHAqXcK6vhXceSCefBK" alt="" width="563"><figcaption><p>CoherenceSyncConfig in CoherenceSync Inspector</p></figcaption></figure>

These edits will in fact be saved not in the Networked Prefab, but on the associated CoherenceSyncConfig asset.

Behind the scenes, the CoherenceSyncConfig object allows coherence to do the following:

* Hard reference the prefab in Editor, this means that whenever we have to do postprocessing in synced prefabs, we don't have to do a lookup or load them from Resources.
* Serialize the method of loading and instantiating this prefab in runtime.
* Soft reference the prefab in Runtime with a GUID, this means we can access the loading and instantiating implementations without having to load the prefab itself into memory.

{% hint style="info" %}
:file\_folder: `Assets/coherence/CoherenceSyncConfigs` is the default location of all CoherenceSyncConfig objects.
{% endhint %}

### The CoherenceSyncConfigRegistry

Every time a CoherenceSyncConfig object is created, it gets added to a registry, represented by a single ScriptableObject of type **CoherenceSyncConfigRegistry**.

This asset is generated by coherence, and is located in :file\_folder: `Assets/coherence`.

In addition to inspecting the assets themselves, you can use the Networked Prefabs window for a holistic view. This window is accessible from the coherence / Networked Prefabs menu item, and from the Hub's Networked Prefabs tab.

<figure><img src="/files/xC98dCrPAayWdQmrrz7d" alt=""><figcaption></figcaption></figure>

This is a great way to see the configuration of different entities next to each other, and it allows you to do mass edits by clicking the **Edit Mode** button.


# Instantiating from CoherenceSyncConfig

{% hint style="warning" %}
This is somewhat of an advance technique. If you're new to coherence and simply looking to instantiate an object, refer to the [Instantiation page](/2.3/manual/networking-state-changes/instantiate-and-destroy-objects).
{% endhint %}

Instead of hard referencing Prefabs in your scripts to [instantiate them](/2.3/manual/networking-state-changes/instantiate-and-destroy-objects) using Unity's own `Instantiate()`, you can reference a `CoherenceSyncConfig` and instantiate Prefab instances through our API. This will respect the custom loading and instantiation rules set on the CoherenceSync component, that is the [instantiator](/2.3/manual/networking-state-changes/asset-management/instantiate-via) specified in **Instantiate via** and the [asset loader](/2.3/manual/networking-state-changes/asset-management/load-via) specified in the **Load via** properties.

In code terms, it utilizes the internal `INetworkObjectProvider` and `INetworkObjectInstantiator` interfaces to load and instantiate the Prefab in a given [networked scene](#user-content-fn-1)[^1].

## Reference to the CoherenceSyncConfig

To instantiate a networked Prefab starting from its CoherenceSyncConfig, you simply need to invoke `GetInstance()`:

```csharp
using Coherence.Toolkit;
using UnityEngine;

public class CoherenceSyncConfigExample : MonoBehaviour
{
    public CoherenceSyncConfig prefabSyncConfig;
    public CoherenceBridge bridge;
    
    private CoherenceSync instance1;
    private CoherenceSync instance2;
    
    void Start()
    {
        // Load the prefab and instantiate it in the current scene
        instance1 = prefabSyncConfig.GetInstance();
        // Load the prefab and instantiate it in the specific networked scene for the given CoherenceBridge
        instance2 = prefabSyncConfig.GetInstance(bridge, Vector3.zero, Quaternion.identity);
    }
    
    private void OnDestroy()
    {
        // Instances have to be destroyed via the ReleaseInstance method, so that its destruction is handle by the 
        // internal INetworkObjectInstantiator
        prefabSyncConfig.ReleaseInstance(instance1);
        prefabSyncConfig.ReleaseInstance(instance2);
    }
}
```

## Reference to a Prefab ("hard reference")

You can also hard reference the Prefab in your script, and then use our CoherenceSync API to instantiate the Prefab:

```csharp
using Coherence.Toolkit;
using UnityEngine;

public class InstantiatorViaCoherenceSyncComponent : MonoBehaviour
{
    // Serialized prefab reference
    public CoherenceSync prefab;
    public CoherenceBridge bridge;

    private CoherenceSync instance1;
    private CoherenceSync instance2;

    void Start()
    {
        // Instantiate it in the current scene
        instance1 = prefab.GetInstance();
        // Instantiate it in the specific networked scene for the given CoherenceBridge
        instance2 = prefab.GetInstance(bridge, Vector3.zero, Quaternion.identity);
    }

    private void OnDestroy()
    {
        // Instances have to be destroyed via the ReleaseInstance method, so that its destruction is handle by the
        // internal INetworkObjectInstantiator
        instance1.ReleaseInstance();
        instance2.ReleaseInstance();
    }
}
```

While the end result is the same, the main difference is that referencing a CoherenceSyncConfig instead of a Prefab makes it a much more scalable and future-proof architecture. Since it doesn't need a Prefab hard reference, you won't have to change the code if the way that the Prefab is loaded into memory changes later on (for example, if you go from Resources to load it via Addressables).

[^1]: A scene with a CoherenceBridge component in it.


# Instantiate via

In coherence, it is possible to specify how a Prefab is instantiated at runtime using the **Instantiate via** option on the CoherenceSync component.

## Built-in instantiators

We support three implementations out of the box: Default, Pool or DestroyCoherenceSync, but you can also [create your own](#creating-your-own-instantiator).

### Default

This instantiator will create a new instance of your Prefab, and when the related network entity is destroyed, this Prefab instance will also be destroyed.

### Pool

This instantiator supports **object pooling**, instead of always creating and destroying instances, the pool instantiator will attempt to reuse existing instances. It has two options:

* **Max Size**: maximum size of the pool for this Prefab, instances that exceed the limit of the pool will be destroyed when returned.
* **Initial Size**: coherence will create this amount of instances on app startup.

### DestroyCoherenceSync

This instantiator will create a new instance for your Prefab, but instead of completely destroying the object when the related network entity is destroyed, it will destroy or disable the CoherenceSync component instead.

## Creating your own instantiator

You can implement the `INetworkObjectInstantiator` interface to create your custom implementations that will be used by coherence when it needs to instantiate a Prefab in the scene.

Custom implementations can be `Serializable` and have their own custom serialized data.

To begin, use the dropdown menu on the CoherenceSync and use the **Create Implementation...** option:

<figure><img src="/files/cj68x6116zTdxm6pRwiG" alt="" width="563"><figcaption><p>Selecting a instantiator or creating your own</p></figcaption></figure>

Let coherence generate the scripts for you, and customise them as you see fit.

Once created, implementations of this interface will appear in the **Instantiate via** dropdown shown above, or in the corresponding CoherenceSyncObject asset.

See [Instantiating from CoherenceSyncConfig](/2.3/manual/networking-state-changes/asset-management/using-coherencesyncconfig-to-instantiate-gameobjects) for two examples of object instantiation using indirect (using `CoherenceSyncConfig`) and direct (using `CoherenceSync`) references.


# Load via

In coherence, it's possible to specify how the Prefab for a network entity will be loaded into memory at runtime using the **Load via** option on the `CoherenceSync`.

## Built-in asset loaders

We support three default implementations, or you can [create your own](#creating-your-own-asset-loader). The three default implementations are Resources, Direct Reference or Addressables:

### Resources

Resources loader will be used if your Prefab is inside a Resources folder. If you wish to use any other type of loading method, you will be prompted to move the Prefab outside of the Resources folder.

### Direct Reference

This loader will be used if your Prefab is outside of a Resources folder, and the Prefab is not marked as Addressable. This means that we will need to hard reference the Prefab in the CoherenceSyncConfig, which means it will always be loaded into memory from the moment you start your game.

### **Addressables**

This option is only available if you have the [Addressables Package](https://docs.unity3d.com/Packages/com.unity.addressables@1.20/manual/index.html) installed.

This loader will be used if your Prefab is marked as an Addressable asset, and it will be soft referenced using Addressables' [`AssetReference`](https://docs.unity3d.com/Packages/com.unity.addressables@1.20/manual/AssetReferences.html) class, meaning it's not loaded in memory at the beginning of the game but it gets loaded on demand, when needed.

When you choose this method, you don't have to implement Addressables code: coherence takes care of doing the loading for you, transparently.

## Creating your own asset loader

You can implement the `INetworkObjectProvider` interface to create your custom implementations that will be used by coherence when we need to load the Prefab into memory.

Custom implementations can be `Serializable` and have your own custom serialized data.

To begin, use the dropdown menu on the CoherenceSync and use the **Create Implementation...** option:

<figure><img src="/files/vBzRX4jni524GYRGI0hr" alt="" width="563"><figcaption><p>Selecting a loader or creating your own</p></figcaption></figure>

Let coherence generate the scripts for you, and customise them as you see fit.

Once created, implementations of this interface will appear in the **Load via** dropdown shown above, or in the corresponding CoherenceSyncObject asset.


# Custom component actions

Even though coherence provides Component Actions out of the box for various component, you can implement your own Component Actions in order to give designers on the team full authoring power on network entities, directly from within the *Configure* window UI.

Creating a new one is simply done by extending the `ComponentAction` abstract class:

{% code title="ComponentAction.cs" %}

```csharp
using UnityEngine;

[System.Serializable]
public abstract class ComponentAction
{
    [SerializeField] internal Component component;
    public Component Component => component;

    public virtual void OnAuthority() { }
    public virtual void OnRemote() { }
}
```

{% endcode %}

Your custom Component Action must implement the following methods:

* `OnAuthority` This method will be called when the object is spawned and you have authority over it.
* `OnRemote` This method will be called when a remote object is spawned and you do not have authority over it.

It will also require the `ComponentAction` class attribute, specifying the type of Component that you want the Action to work with, and the display name.

For example, here is the implementation of the Component Action that we use to disable Components on remote objects:

{% code title="ComponentAction.cs" %}

```csharp
using Coherence.Toolkit;
using UnityEngine;

[ComponentAction(typeof(Behaviour), "Disable")]
public class DisableBehaviourComponentAction : ComponentAction
{
    public override void OnAuthority()
    {
        var b = Component as Behaviour;
        b.enabled = true;
    }

    public override void OnRemote()
    {
        var b = Component as Behaviour;
        b.enabled = false;
    }
}
```

{% endcode %}


# Custom bindings

Extending what can be networked from a Component

{% hint style="info" %}
This is an **advanced** topic that aims to bring access to **coherence**'s internals to the end user.
{% endhint %}

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:

```csharp
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`.

<figure><img src="/files/C6JtMaapym8ZpW1q25EQ" alt=""><figcaption><p>The Inventory component does not expose the inventory items by default.</p></figcaption></figure>

### 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:

```csharp
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.

{% hint style="info" %}
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`.
{% endhint %}

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

```csharp
using System.Collections.Generic;
using Coherence.Editor;
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.

```csharp
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;
    }
}
```

{% hint style="info" %}
For the full list of supported binding types, see [Supported types in Commands and Bindings](/2.3/manual/networking-state-changes/supported-types).
{% endhint %}

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

<figure><img src="/files/qt6rrbhSQWlFqBxz1kV7" alt=""><figcaption><p>The Inventory items can now be synced across the network.</p></figcaption></figure>


# Supported types

CoherenceSync can handle the following types:

| Type                                                                                                                  | Remarks                                                                                                |
| --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| Built-in types: `bool`, `byte`, `sbyte`, `short`, `ushort`, `char`, `int`, `uint`, `float`, `long`, `ulong`, `double` |                                                                                                        |
| `string`                                                                                                              | Limited by packet size. See [syncing big data](/2.3/manual/networking-state-changes/syncing-big-data). |
| `byte[]`                                                                                                              | Limited by packet size. See [syncing big data](/2.3/manual/networking-state-changes/syncing-big-data). |
| `UnityEngine.Color`                                                                                                   |                                                                                                        |
| `UnityEngine.Vector2`, `UnityEngine.Vector3`, `UnityEngine.Quaternion`                                                |                                                                                                        |
| `GameObject`                                                                                                          | Must be part of a Networked Prefab. What's networked is the underlying Entity reference.               |
| Classes that inherit from `Component` (incl. `MonoBehaviour`s)                                                        | Must be part of a Networked Prefab. What's networked is the underlying Entity reference.               |
| ClientID                                                                                                              |                                                                                                        |
| Entity                                                                                                                |                                                                                                        |
| Custom enumerations — `enum`                                                                                          | Casted to `int` baking type.                                                                           |


# Baking

In coherence, you don't write the network code. Instead, you decide what to network and let **baking** figure out the lower level details.

{% hint style="success" %}
Baking is **not optional**. You **must** bake before you enter Play Mode or create builds, for the network-related functionality to work properly.
{% endhint %}

Baking does two main things:

1. Creates or updates a schema file, that ultimately serves as the communication protocol between the client and the Replication Server.
2. Creates the necessary Unity scripts (baked scripts) to wire the data you want to network from your Networked Prefabs into the lower level layers of the network stack.

The generated schema and baked scripts are created within `Assets/coherence`.

Baked scripts access your code directly. Changing the definitions of variables or methods that are already baked might get your project to not compile, and will require regenerating the baked scripts.

In the coherence Hub you can check what's your current **schema id** — this identifier acts as a **unique version number** that must match between clients for them to see each other within the network.

<figure><img src="/files/i30hLyHmBP0Kiqatvzjc" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}
Since baking changes the schema, you need to restart your Replication Server (if open) after baking.

Likewise, update your coherence Cloud World(s) to point to the new schema (if it applies for your case).

Schema changes are **always breaking changes**, meaning two clients will not see each other if they try to stablish connection using different schemas.
{% endhint %}

To learn more about the role of schemas in coherence, refer to the [How does coherence work](/2.3/overview) section.

### How to Bake

There's different ways to trigger a bake.

* Top menu: `coherence > Bake`
* coherence Hub: `Bake Now` button
* Project window: `Assets > coherence` bake button
* Main toolbar: bake button (requires enabling it first — see [Bake button in Main Toolbar](#bake-button-in-main-toolbar))
* API: [`BakeUtil.Bake()`](https://unityapi.coherence.io/docs/latest/api/Coherence.Editor.BakeUtil.Bake.html)

<figure><img src="/files/ySPGUd5uJwYNptKnTz0M" alt=""><figcaption><p>Baking via top menu</p></figcaption></figure>

<figure><img src="/files/Vq7ti4YlBQtewdYxZTKO" alt=""><figcaption><p>Baking via coherence Hub</p></figcaption></figure>

<figure><img src="/files/lRbPdYSCU57zlw02Dr5S" alt=""><figcaption><p>Baking via Project window</p></figcaption></figure>

<figure><img src="/files/8hpYaBXPJlICvLXroIJb" alt=""><figcaption><p>Baking via main toolbar — needs to be enabled manually</p></figcaption></figure>

## Bake Button in Main Toolbar

To enable or disable the Bake Button in Unity's Main Toolbar, right click near the Play Mode buttons, or click on the Kebab menu on the right side of the Main Toobar. A context menu will pop up. Select `coherence > Bake`.

<figure><img src="/files/Wrf9rdOtqwYiJPSrdUN2" alt=""><figcaption></figcaption></figure>

You can choose where in the Main Toolbar to render this button, by enabling Edit Mode within the context menu.

{% hint style="info" %}
There's a few settings you can fine tune to your desired workflow needs. Check out the [settings](/2.3/manual/project-settings) section.
{% endhint %}

## Modifying baked Networked Prefabs

When you network variables or methods on your Networked Prefab and bake, coherence generates baked scripts that **access your code directly**, without using reflection. This means that whenever you change your game logic, you might break compilation by accident.

For example, if you have a `Health.cs` script which exposes a `public float health;` field, and you toggle `health` in the *Configure* window and bake, the generated baked script will access your component via its type, and your field via field name.

Like so:

```csharp
var healthComponent = GetComponent<Health>();
...
var healthField = healthComponent.health;
```

If you decide you want to change the component name or any of your bound member names, Unity can fail to compile, since baked scripts will still refer to the former names (i.e., the names as they were when baking was done).

In this example, we will be removing `health` and adding `health2` in its place.

```csharp
//public float health;
public float health2;
```

When saving this change and focusing on Unity, compilation errors will appear.

coherence includes a **watchdog** that is able to catch these compilation problems related to baked scripts, easing your way into getting things back to work.

<figure><img src="/files/Ts1GtTgh2cBXSW3uv20Z" alt=""><figcaption></figcaption></figure>

The watchdog suggests that you delete the baked folder, and then diagnose the state of your Networked Prefabs. Once Unity recompiles the project, you will be presented with the *Network Prefabs* window, to spot what Prefabs might require further attention.

{% hint style="info" %}
A `Do Nothing` option is provided as a fallback, in case the watchdog is not able to successfully resolve the situation. If you're manually debugging through baked code, and want to see what's going wrong (useful if you want to report issues to us!), you can use this option. Most of the time though, you're going to want to `Delete Baked Scripts and Diagnose`.
{% endhint %}

<figure><img src="/files/EXNCalAFll7z6olvHP2c" alt=""><figcaption><p>The Networked Prefabs window offers a holistic view so you can identify issues easily</p></figcaption></figure>

In the Configure window of the Networked Prefab that shows issues, you can easily spot variables that can't be resolved properly. In our example, `health` is no longer valid since we've moved it elsewhere (or deleted it).

![](/files/JgR1YngGUCUQa1H1E9JQ)

Now, we can manually rebind our data: unbind `health` and bind `health2`. Once done, we can safely bake again.

{% hint style="success" %}
Remember to bake again after you fix your Networked Prefabs.
{% endhint %}


# Conditional Compilation

Sometimes, there's a need for parts of the code to be present only in specific builds. For example, you might want cheat codes to be present only in debug builds so you can test your game quickly, but have them removed in release builds, so players can't use them.

One of the common ways to handle that is to use [conditional compilation](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives#conditional-compilation) which can be achieved with [scripting symbols](https://docs.unity3d.com/Manual/custom-scripting-symbols.html) in Unity. The cheat codes example from above could could look as follows:

```csharp
public class CheatManager : MonoBehaviour
{
#if DEVELOPMENT_BUILD
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.C))
        {
            ActivateCheats();
        }
    }
    
    void ActivateCheats()
    {
        Debug.Log("Cheats Activated!");
        // ... cheat functionality
    }
#endif
}
```

The same need of conditionally compiling out functionality can arise with networked entities. We can synchronize additional data for troubleshooting or provide some cheat commands, all of which should be removed in release builds.

To solve this, coherence provides a `BakeCondition` attribute which can be applied to a networked component. The baked code for that component will be compiled only if the condition from the attribute is met:

```csharp
[RequireComponent(typeof(CoherenceSync))]
[BakeConditional("DEVELOPMENT_BUILD")]
public class CheatManager : MonoBehaviour
{
    [Sync]
    public bool CheatsEnabled;
    
    [Command]
    public void Cheat_Teleport(Vector3 position) { /* ... */ }
}
```

In the example above, the `CheatsEnabled` variable and `Cheat_Teleport` command will be networked only if the DEVELOPMENT\_BUILD symbol is present (it is automatically added by Unity when *Development Build* is selected in the build profile).

{% hint style="info" %}
You might be wondering why it's not an option to wrap networked members in the #ifdef just like in the first example. The problem with that approach is that baking is not part of the build process—it happens earlier. That means symbols between baking and building might differ, likely leading to baked code compilation errors upon build.
{% endhint %}


# Client connections

Communication between Clients

### Overview <a href="#overview" id="overview"></a>

**ClientConnections** are `CoherenceSyncs` that the `CoherenceBridge` can handle for you and that let you uniquely identify users connected, find them by their ID, and easily send commands between those users.

When using ClientConnections, `CoherenceBridge` will spawn a `CoherenceSync` for each connection (Client or Simulator). Those `CoherenceSyncs` are subject to a different ruleset than standard `CoherenceSyncs`:

* They can't be created or destroyed by the Client - they are always driven by `CoherenceBridge`.
* They are global — they are replicated across Clients regardless of the [Live Query](/2.3/manual/components/coherence-live-query) extent.
* Authority cannot be transferred.

{% hint style="info" %}
Despite being CoherenceSync prefabs, Client Connections behave differently to normal entities. Please, mind this if you're using the convenience offered by CoherenceBridge to spawn CoherenceSync prefabs.
{% endhint %}

ClientConnections shine whenever there's a need to communicate something to all the connected players. Usage examples:

* Global chat
* Game state changes: game started, game ended, map changed
* Server announcements
* Server-wide leaderboard
* Server-wide events

### Enabling ClientConnections <a href="#enabling-client-messages" id="enabling-client-messages"></a>

The global nature of **ClientConnections** doesn't fit all game types - for example, it rarely makes sense to keep every Client informed about the presence of all players on the server in an MMORPG. If this is your use case, don't set **ClientConnections** on your `CoherenceBridge`.

To enable **ClientConnections***,* enable *Create Global Query* in your [`CoherenceBridge`](/2.3/manual/components/coherence-bridge):

<figure><img src="/files/ShCbu1QOJOk0BA2ozEt5" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Disabling *Create Global Query* on one Client doesn't affect other Clients, i.e. the **Client Connection** of this Client will still be visible to other Clients that create a *Global Query*.
{% endhint %}

### Connection management <a href="#id-3-create-a-client-connection-prefab" id="id-3-create-a-client-connection-prefab"></a>

Most of the **ClientConnection** functionality is accessible through the `CoherenceBridge.ClientConnections` object:

```csharp
using System.Collections.Generic;
using Coherence.Connection;
using Coherence.Toolkit;
using UnityEngine;

public class ExampleGameManager : MonoBehaviour
{
    public CoherenceBridge Bridge;

    void Start()
    {
        // Raised whenever a new connection is made (including the local one).
        Bridge.ClientConnections.OnCreated += connection =>
        {
            Debug.Log($"Connection #{connection.ClientId} " +
                      $"of type {connection.Type} created.");
        };

        // Raised whenever a connection is destroyed.
        Bridge.ClientConnections.OnDestroyed += connection =>
        {
            Debug.Log($"Connection #{connection.ClientId} " +
                      $"of type {connection.Type} destroyed.");
        };

        // Raised when all initial connections have been synced.
        // Called individually by each Bridge when a player joins and syncs.
        Bridge.ClientConnections.OnSynced += connectionManager =>
        {
            Debug.Log($"ClientConnections are now ready to be used.");
        };
    }
    
    void Update()
    {
        // IMPORTANT: All of the connection retrieving calls may return null 
        // if the connection system was not turned on, not initialized yet,
        // or simply if the connection was not found.
        
        // Specifies how many clients are in this session (Room or World).
        int clientCount = Bridge.ClientConnections.ClientConnectionCount;
        
        // Returns connection objects for all connections in this session.
        IEnumerable<CoherenceClientConnection> allConnections
            = Bridge.ClientConnections.GetAll();

        // Returns all connections except for the local one.
        IEnumerable<CoherenceClientConnection> otherConnections
            = Bridge.ClientConnections.GetOther();

        // Returns connection object of the local user.
        CoherenceClientConnection myConnection
            = Bridge.ClientConnections.GetMine();

        // Returns connection object of the Simulator (if one is connected).
        CoherenceClientConnection simulatorConnection
            = Bridge.ClientConnections.GetSimulator();

        // Retrieves a connection by its ClientID.
        CoherenceClientConnection selectedConnection
            = Bridge.ClientConnections.Get(myConnection.ClientId);

        // Retrieves a connection by its EntityID (warning: requires
        // a connection Prefab with a CoherenceSync attached).
        if (myConnection.Sync != null)
        {
            selectedConnection
                = Bridge.ClientConnections.Get(myConnection.Sync.EntityID);
        }

        // Specifies if this is a Client or a Simulator connection.
        ConnectionType connectionType = selectedConnection.Type;

        // Specifies if this is a local connection (belonging to the
        // local user).
        bool isMine = selectedConnection.IsMyConnection;

        // Returns a GameObject associated with this connection.
        // Applicable only if connection Prefabs are used.
        GameObject connectionGameObject = selectedConnection.GameObject;
    }
}
```

Each connection is represented by a plain C# `CoherenceClientConnection` object. It contains all the important information about a connection - its `ClientID`, `Type`, whether it `IsMyConnection`, and a reference to the `GameObject` and `CoherenceSync` associated with it.

{% hint style="warning" %}
The `CoherenceClientConnection.ClientID` is guaranteed to not change during a connection's lifetime. However, if a Client disconnects and then connects again to the same Room/World, a new `ClientID` will be assigned (since a new connection was established).
{% endhint %}

### ClientConnection objects

Each **ClientConnection** can have a `CoherenceSync` automatically being spawned and associated with it. Those objects, like any other objects with `CoherenceSync`, can be used for syncing properties or sending messages, with a little twist - they are global and thus not limited by the `CoherenceLiveQuery` extent. That makes them perfect candidates for operations like:

* Syncing global information - name, stats, tags, etc.
* Sending global messages - chat, server interaction

To enable connection objects:

#### 1. Create a ClientConnection Prefab <a href="#id-3-create-a-client-connection-prefab-2" id="id-3-create-a-client-connection-prefab-2"></a>

This step is described in detail in the [Prefab setup section](/2.3/getting-started/setup-a-project/prefab-setup). In short, it is enough to create a Prefab with a `CoherenceSync` and a custom component (`PlayerConnection` in this example):

![PlayerConnection prefab](https://gblobscdn.gitbook.com/assets%2F-MWd0ZPEK7vE9nkE0b7G%2F-MdqCDf3w4s6f3x7-nqQ%2F-MdqRCkj3rMik-vFzHRx%2FScreenshot_46.png?alt=media\&token=887e5109-e8ed-4157-a9f9-7fe897e63cff)

#### 2. Link a ClientConnection Prefab to the `CoherenceBridge` <a href="#id-4-link-the-connection-prefab-to-the-bridge" id="id-4-link-the-connection-prefab-to-the-bridge"></a>

For the system to know which object to create for every new Client connection, we have to link our Prefab to the `CoherenceBridge`. Simply drag the prefab to the *Client* field in the inspector:

<figure><img src="/files/y2aj4CweOg4OwbVrxLEo" alt=""><figcaption></figcaption></figure>

From now on every new connection will be assigned an instance of this Prefab, which can be accessed through the `CoherenceClientConnection.GameObject` property.

#### Prefab selection <a href="#id-3-create-a-client-connection-prefab" id="id-3-create-a-client-connection-prefab"></a>

Note that there's a separate field for the *Simulator Connection Prefab*. It can be used to spawn a completely different object for the Simulator connection that may contain Simulator-specific commands and replicated properties. If the field is left empty, no object will be created for the Simulator connection.

The Prefab selection process can be also controlled from code using the `CoherenceBridge.ClientConnections.ProvidePrefab` callback:

```csharp
using Coherence.Toolkit;
using UnityEngine;

public class ExampleGameManager : MonoBehaviour
{
    public CoherenceSync CustomConnectionPrefab;
    private CoherenceBridge bridge;
    
    void Start()
    {
        bridge = FindAnyObjectByType<CoherenceBridge>();
        bridge.ClientConnections.ProvidePrefab += (clientId, connectionType) =>
        {
            return CustomConnectionPrefab;
        };
    }
```

{% hint style="info" %}
A Prefab provided through the `ProvidePrefab` callback takes precedence over Prefabs linked in the Inspector.
{% endhint %}

### Client messages <a href="#id-3-create-a-client-connection-prefab" id="id-3-create-a-client-connection-prefab"></a>

Client messages is a shortcut to send [Network Commands](/2.3/manual/networking-state-changes/commands) using a `CoherenceClientConnection` object as the target instead instead of a `CoherenceSync`. The end recipient of the command will however still be the `CoherenceSync` associated with the [ClientConnection Prefab](#clientconnection-objects), just like a regular Network Command.

Preparing to use Client messages requires the same approach as exposing a command on a script present on the **Client Connection Prefab** that we set up in the `CoherenceBridge` in the previous section:

```csharp
using UnityEngine;

public class PlayerConnection : MonoBehaviour
{
    // My chat command
    public void OnChatMessage(string message)
    {
        Debug.Log($"Received chat message: {message}");
    }
}
```

Don't forget to bind the method to define a Command:

<figure><img src="/files/uqDr6EoUM1RCMPoBUOW3" alt=""><figcaption></figcaption></figure>

That same Command can now be sent using the `CoherenceClientConnection.SendClientMessage` method:

```csharp
using UnityEngine;
using Coherence;
using Coherence.Toolkit;

public class PlayerConnection : MonoBehaviour
{
    void Start()
    {
        var bridge = FindObjectOfType<CoherenceBridge>();
        CoherenceClientConnection myConnection = bridge.ClientConnections.GetMine();

        myConnection.SendClientMessage<PlayerConnection>(nameof(OnChatMessage),
            MessageTarget.Other, "Hello!");
    }

    // My chat command
    public void OnChatMessage(string message)
    {
        Debug.Log($"Received chat message: {message}");
    }
}
```

If the `ClientID` of the message recipient is known we can use the `CoherenceBridge.ClientConnections` directly to send a Client message:

```csharp
private ClientID lastClientId;

private void OnConnectionCreated(CoherenceClientConnection clientConnection)
{
    if (!clientConnection.IsMyConnection)
    {
        lastClientId = clientConnection.ClientId;
    }
}

public void SendMessageToLastConnection(string message)
{
    var bridge = FindAnyObjectByType<CoherenceBridge>();
    bridge.ClientConnections.SendMessage<PlayerConnection>("OnChatMessage",
        lastClientId, MessageTarget.StateAuthorityOnly, "Hello!");
}
```


# Replication server

The Replication Server is an **essential part** of coherence. It is an executable that replicates the state of the world to all connected Clients and [Simulators](/2.3/manual/simulation-server).

To understand what is happening in the game world, and to be able to contribute your simulated values, you need to **connect** to a Replication Server.

<figure><img src="/files/7g6kIXBvFnq8LNpwiai8" alt="" width="563"><figcaption><p>In coherence, the Replication Server is always at the center of the network</p></figcaption></figure>

## Start a Replication Server

A Replication Server can be run in the [coherence Cloud](/2.3/hosting/coherence-cloud), but while developing we recommend that you first start with one running locally on your computer. coherence is designed so you can easily develop everything locally first, and then deploy to the Cloud without any change to the game.

You can start a local Replication Server from the **coherence Hub**, in the Replication Servers tab, just by clicking on the buttons there:

<figure><img src="/files/avhBuDAq5aDQ2LeKU1Oj" alt=""><figcaption></figcaption></figure>

To understand the two types of Replication Server that you can run, refer to the [Rooms and Worlds ](/2.3/manual/replication-server/rooms-and-worlds)page.

{% hint style="info" %}
You can also start the Replication Server using the top menu items **coherence > Run Replication Server for Rooms** and **Run Replication Server for Worlds**.
{% endhint %}

If you start a Replication Server locally, a new Terminal window will open.

<figure><img src="/files/zJS6puY56JmZgLQChYNX" alt="" width="375"><figcaption><p>A Replication Server running correctly</p></figcaption></figure>

## Connect to a Replication Server

Once a Replication Server is running, connection to it can be established using a `CoherenceBridge` component.

The `CoherenceBridge` needs to know what to connect to. A simple way to connect is to use one of our **Sample Connection UIs**:

<figure><img src="/files/iEWuqmnmckZtSdPb5HwR" alt=""><figcaption><p>The World Connection UI sample</p></figcaption></figure>

[Sample Connection UIs](/2.3/getting-started/samples-and-tutorials/samples-connection-uis) scan the available Worlds and Rooms, and prepare the endpoint data so that the `CoherenceBridge` can find the Replication Server. You can find them in the SDK package itself, by going to Unity's Package Manager, and then exploring the package samples.

Later on, when you are developing a full game, you will probably recreate your own UI, using the [Replication Server APIs](/2.3/manual/replication-server/replication-server-api).

{% hint style="success" %}
For more information on your first time using a Replication Server, refer to the [Local Development](/2.3/getting-started/setup-a-project/local-development) page in our getting started guide.
{% endhint %}

## Send and receive frequencies

The Replication Server supports different packet frequencies for sending and receiving data.

The send frequency is the frequency that the Replication Server uses to send packets to a given Client. Each Client can be sent packets at different times, but the packet receive frequency for any Client will not exceed the Replication Server's send frequency.

The receive frequency is the maximum frequency at which the Replication Server expects to receive packets from any Client, before throttling. If a Client sends packets to the Replication Server at a higher than expected frequency, that Client will receive a command to slow down sending. If the Client doesn't respect the command to throttle packet sending then the Client is disconnected after a time. All extra packets received by the Replication Server, after a threshold based on the receive frequency, are dropped and not processed. This is to prevent malicious Clients from flooding the Replication Server. The Unity SDK handles throttling automatically.

It is possible for the Replication Server to temporarily request Clients to reduce their packet send rates if the processing load of the Replication Server is too high. This is automatic and send rates from the affected Clients are commanded to resume once the load is reduced.

### Adjusting send and receive frequencies

Low and consistent send rates from the Replication Server allow for optimal bandwidth use and still support a smooth stream of updates to Clients. Try different rates during local replication tests to see what works well for your game.

For a **locally hosted Replication Server**, you can edit the send and receive frequencies by using the **CLI arguments** `--send-frequency` and `--recv-frequency`. Or by changing it in the *coherence Settings* -> *Local Replication Server* -> *Send Frequency* / *Recv Frequency*.

On the dashboard, the packet frequencies for sending and receiving data can be adjusted **per project** too. It is part of the *Advanced Config* section of *Worlds create/edit* and *Rooms* pages of the dashboard.

{% hint style="success" %}
Adjusting the send and receive frequencies on the dashboard is available for paid plans.
{% endhint %}

## Maximum entity count

The Replication Server imposes limits on the total number of existing entities. The default maximum entity count is 65 536, but it can be increased to up to 2³². The maximum number of entities a single Client can own is capped at 32 768, and the same limit applies to the maximum number of remote entities a single Client can see.

To adjust the default maximum entity count on a locally run Replication Server, you can use the [CLI argument](/2.3/manual/replication-server/command-line-interface#worlds) `--max-entities` for worlds, or pass the value at room creation time via `SelfHostedRoomCreationOptions.MaxEntities`.

The default value cannot yet be adjusted on the cloud-hosted Replication Servers. If you need this changed, please write to **<devrel@coherence.io>**.

## Maximum query count per client

The Replication Server imposes limits on number of queries a Client can create. This is important to stop malicious Clients from throttling the Replication Server by creating huge number of queries.

The default maximum query count per Client is 15. Other than limiting the query count per Client, the Replication Server also limits the total count of all queries in the Room/World to `maxQueriesPerClient * numberOfConnectedClients`.

To adjust the default number on a locally run Replication Server you can use the [CLI argument](/2.3/manual/replication-server/command-line-interface) `--max-queries-per-client`.

The default value cannot yet be adjusted on the cloud-hosted Replication Servers. If you need this changed, please write to **<devrel@coherence.io>**.


# Rooms and worlds

**coherence** provides two types of spaces where realtime gameplay can happen: [Rooms](/2.3/hosting/coherence-cloud/configure-rooms) and [Worlds](/2.3/hosting/coherence-cloud/manage-worlds). In addition to these, [Lobbies](/2.3/hosting/coherence-cloud/game-services/lobbies) provide functionality for players to meet before a match, and to chat.

## Rooms

Rooms are best for session-based gameplay where the match between players takes place in a short-lived environment. You can use the Online Dashboard to [configure Rooms](/2.3/hosting/coherence-cloud/configure-rooms).

#### Use case

A good example is a first person shooter multiplayer match. The match takes place between two teams in a single game session, and players enter through a lobby and matchmaking. When the match is concluded, the multiplayer environment the match took place in (the Room) is closed and players return to a lobby.

This is one example of how Rooms can be used, but it is by no means the only use case. The important distinction between Rooms and Worlds (see below) is that Rooms are relatively short-lived and are meant to be created and closed by the Game Client through the **coherence** SDK.

See [Rooms API](/2.3/hosting/coherence-cloud/coherence-cloud-apis/rooms).

## Worlds

Worlds, as opposed to Rooms, are longer-lived and permanent multiplayer environments provided by **coherence**. Using the Online Dashboard, your project will easily define and [manage your World](/2.3/hosting/coherence-cloud/manage-worlds) configurations.

See [Worlds API](/2.3/hosting/coherence-cloud/coherence-cloud-apis/worlds).

#### **Use case**

A good example of a World is a permanent environment for an Massively Multiplayer Game (MMO). Regardless of the number of players connected, the environment is always available, and players can connect and disconnect at will.

Entities can be permanently saved in the World so that even if there are no active connections, they still persist when players do connect.

{% hint style="warning" %}
Note that upon shutting down the World or restarting its Replication Server, the state of persistence is lost under current implementation.
{% endhint %}

{% hint style="info" %}
**Rooms and Worlds together**

Your project does not have to choose one or the other. A project in **coherence** can contain both World and Rooms.

The primary difference in the configuration and usage of Room and Worlds is that Worlds are managed in the Developer Portal, whereas Rooms are created and managed through the SDK.

**Use case**

A good example of this scenario is again, our MMO. Although players connect to a permanent and persistent World, they may enter a dungeon instance with other players. These dungeon instances can be Rooms.
{% endhint %}

{% hint style="info" %}
**What about Lobbies?**

In coherence, [Lobbies](/2.3/hosting/coherence-cloud/game-services/lobbies) work slighlty differently than Rooms and Worlds, and in fact they are not run by a Replication Server.

Lobbies are a convenient way to do matchmaking between player accounts, filter players based on their attributes, and provide a way for them to communicate among each other.

For more info, you can read the [Lobbies](/2.3/hosting/coherence-cloud/game-services/lobbies) section.
{% endhint %}


# Connecting to a replication server

This page illustrates a few API you can use to interact with the Replication Server.

## Connection to a Replication Server

When the Replication Server is running, you connect to it using the `Connect` method.

#### Connect to a local Replication Server

Before you connect, make sure you've [baked](/2.3/manual/baking-and-code-generation). Then, (re)start a Replication Server for Worlds or Rooms. In this example, we're going for Worlds.

<figure><img src="/files/PP3qX4oa4oSQzRSWTibD" alt=""><figcaption></figcaption></figure>

```csharp
using Coherence.Toolkit;
using UnityEngine;

public class ConnectToLocal : MonoBehaviour
{
    private CoherenceBridge bridge;

    private void Start()
    {
        if (!CoherenceBridgeStore.TryGetBridge(out bridge))
        {
            bridge = new GameObject(nameof(CoherenceBridge)).AddComponent<CoherenceBridge>();
        }

        bridge.onConnected.AddListener(HandleConnected);
        bridge.onDisconnected.AddListener(HandleDisconnected);
        bridge.onLiveQuerySynced.AddListener(HandleLiveQuerySynced);

        bridge.Connect();
    }
}

```

After trying to connect you might be interested in knowing whether the connection succeeded. The Connect call will run asynchronously and take around 100 ms to finish, or longer if you connect to a remote Server.

#### Respond to connection events

```csharp
using Coherence.Connection;
using Coherence.Toolkit;
using UnityEngine;

public class ConnectToLocal : MonoBehaviour
{
    private CoherenceBridge bridge;

    private void Start()
    {
        if (!CoherenceBridgeStore.TryGetBridge(out bridge))
        {
            bridge = new GameObject(nameof(CoherenceBridge)).AddComponent<CoherenceBridge>();
        }

        bridge.onConnected.AddListener(HandleConnected);
        bridge.onDisconnected.AddListener(HandleDisconnected);
        bridge.onLiveQuerySynced.AddListener(HandleLiveQuerySynced);

        bridge.Connect();
    }

    private static void HandleConnected(CoherenceBridge bridge) { /* ... */ }

    private static void HandleLiveQuerySynced(CoherenceBridge bridge) { /* ... */ }

    private static void HandleDisconnected(CoherenceBridge bridge, ConnectionCloseReason reason) { /* ... */ }

    private void OnDestroy()
    {
        bridge.onConnected.RemoveListener(HandleConnected);
        bridge.onDisconnected.RemoveListener(HandleDisconnected);
        bridge.onLiveQuerySynced.RemoveListener(HandleLiveQuerySynced);
    }
}
```

{% hint style="info" %}
The OnLiveQuerySynced event is triggered when the initial game state has been synced to the client. More specifically, it is fired when all entities found by the Client's first Live Query have finished replicating. This is the last step of the connection process and is usually a good place to start the game simulation.
{% endhint %}

{% hint style="info" %}
To connect to Cloud-hosted Servers, see [Rooms API](/2.3/hosting/coherence-cloud/coherence-cloud-apis/rooms) and [Worlds API](/2.3/hosting/coherence-cloud/coherence-cloud-apis/worlds) documentation.
{% endhint %}

{% hint style="info" %}
Check **Run in Background** in the *Unity settings* under *Project Settings > Player* so that the Clients continue to run even when they're not the active window.
{% endhint %}

To connect with multiple Clients locally, publish a build for your platform (*File > Build and Run*, details in [Unity docs](https://docs.unity3d.com/Manual/PublishingBuilds.html)). Run the Replication Server and launch the build any number of times. You can also enter Play Mode in the Unity Editor.

{% hint style="info" %}
For Mac Users: You can open new instances of an application from the Terminal:

```bash
open -n <path to .app>
```

{% endhint %}


# Replication server CLI

How to use the Replication server in the command-line

To start a local Replication Server yourself, you can copy the command to clipboard from within the **Replication Server** tab in coherence Hub.

<figure><img src="/files/DzOshFNFKF8nJl7JkWkF" alt=""><figcaption></figcaption></figure>

Pasting this command into a terminal allows you to launch a Replication Server with specific settings.

{% hint style="info" %}
Scripts holding these command can be also found at:

`<project-path>/Library/coherence/run-replication-server-[rooms|worlds].[bat|sh]`&#x20;
{% endhint %}

To see a full list of flags available:

```shellscript
path/to/replication-server rooms --help
path/to/replication-server world --help
```

#### Minimal working example

For worlds, `--schema` must be provided:

{% code overflow="wrap" %}

```shellscript
path/to/replication-server world --schema "<sdk-path>/Coherence.Toolkit/Toolkit.schema,<project-path>/Assets/coherence/Gathered.schema"
```

{% endcode %}

For rooms, `--default-schema` must be provided:

{% code overflow="wrap" %}

```shellscript
path/to/replication-server rooms --default-schema "<sdk-path>/Coherence.Toolkit/Toolkit.schema,<project-path>/Assets/coherence/Gathered.schema"
```

{% endcode %}

{% hint style="info" %}
Substitute `<sdk-path>` with the path to a coherence package installation, and `<project-path>` is the path to your Unity project root.

If you installed coherence through the Asset Store, check `<project-path>/Packages/io.coherence.sdk`. If you installed through the Scoped Registry, check `<project-path>/Library/PackageCache/io.coherence.sdk@<hash>`.

`Toolkit.schema` and `Gathered.schema` must be provided.
{% endhint %}

#### Allowing connections from other machines

By default, the Replication Server binds to `127.0.0.1`, which means only connection from within the local machine will be accepted. To accept connections from any other machine, use `--local-ip-override "0.0.0.0"`.


# Optimization

### Bandwidth is limited

No matter how fast the internet becomes, conserving bandwidth will always be important. Some Game Clients might be on poor quality mobile networks with low upload and download speeds, or have high ping to the Replication Server and/or other Clients, etc.

Additionally, sending more data than is required consumes more memory and unnecessarily burdens the CPU and potentially GPU, which could add to performance issues, and even to quicker battery drainage.

![](/files/-MWi5Q8V8gpDTqPRaIeG)

### Optimization techniques

In order to optimize the data we are sending over the network, we can employ various techniques built into the core of **coherence**.

* **Delta-compression (automatic).** When possible, only send differences in data, not the entire state every frame.
* **Compression and quantization (automatic and configurable).** Various data types can be compressed to consume less bandwidth that they naturally would.
* **Simulation frequency (configurable)**. Most Entities do not need to be simulated at 60+ frames per second.
* **Levels of detail (configurable).** Entities need to consume less and less bandwidth the farther away they move from the observer.
* **Area of interest.** Only replicate what we can see.


# Queries

**Queries** are not only a way to optimise, but a fundamental tool for Clients to specify what part(s) of the online world they are interested in.

With them, the Replication Server can filter the information to send based on each Client's interest, and thus greatly optimise network traffic.

<figure><img src="/files/6hVrgVMZUivkmn8TfjIy" alt=""><figcaption><p>In the left window, Player2 is not visible because it's outside of Player1's LiveQueries</p></figcaption></figure>

At the moment, coherence offers three ways to filter network entities: [**Live Query**](/2.3/manual/components/coherence-live-query)**,** [**Tag Query**](/2.3/manual/components/coherence-tag-query) **and** [**Global Query**](/2.3/manual/components/coherenceglobalquery).

* With [**Live Queries**](/2.3/manual/components/coherence-live-query) the filtering is volume-based, kind of like moving a torch to look around in a dark cave.
* With [**Tag Queries**](/2.3/manual/components/coherence-tag-query) even distant entities can be seen, provided they have the right [Tag](/2.3/manual/components/coherence-sync#tag).
* With [**Global Queries**](/2.3/manual/components/coherenceglobalquery) any entities marked as [Is Global](/2.3/manual/components/coherence-sync#is-global) can be seen.

{% hint style="warning" %}
You **need at least one** query in your scene, or you won't see anything update over the network. All queries are combined and a union of all matching entities are made visible to the client.
{% endhint %}

When a non-authoritative entity **falls outside** of all queries, it gets **destroyed** (or returned to an object pool). When it gets back in, it gets re-instantiated (or taken out of the pool). If the right properties are synced, the entity's state will be automatically restored by coherence, making the player feel like that entity never disappeared.

{% hint style="info" %}
Queries only filter network entities that are **non-authoritative**. Your own entities will never be destroyed for falling outside of a query.
{% endhint %}

## Queries are additive

When using queries and adding more than one, they act in an **additive** way.

So for instance, two overlapping **LiveQueries** will define a bigger area.

Similarly, a **LiveQuery** + a **TagQuery** will add up, looking for entities both within a range but also for the ones that have a certain tag, regardless of position.

{% hint style="info" %}
Non-additive filtering will come in a future version of coherence.
{% endhint %}

## Runtime changes

It is a very common pattern to **move** a LiveQuery around, following a player character or the camera, to ensure the visible entities are updated.

In addition to this, queries can be **turned on/off** (simply by disabling them), or **their properties can be changed** at runtime (like radius, position, or tag), making for a very dynamic tool to optimise bandwidth.

## Queries are personal

Queries are per-Client, meaning that each Client (or Simulator!) has its own queries and thus sees different parts of the simulation.

{% hint style="success" %}
Queries can also be used for cheat prevention, see [Server authoritative setup](/2.3/manual/networking-state-changes/authority/server-authoritative-setup) for more information.
{% endhint %}


# Level of detail (LOD)

{% hint style="info" %}
This feature requires [baking](/2.3/manual/baking-and-code-generation).
{% endhint %}

## Motivation

**coherence** can support large game worlds with many objects. Since the amount of data that can be transmitted over the network is limited, it's very important to only send the most important things.

You already know a very efficient tool for enabling this – the [LiveQuery](/2.3/manual/optimization/areas-of-interest). It ensures that a client is only sent data when an object in its vicinity has been updated.

Often though, there is a possibility for an even more nuanced and optimized approach. It is based on the fact that we might not need to send as much data for an entity that is far away, compared to a close one. A similar technique is often used in 3D-programming to show a simpler model when something is far away, and a more detailed when close-up.

This idea works really well for networking too. For example, when another player is close to you it's important to know exactly what animation it is playing, what it's carrying around, etc. When the same player is far off in the horizon, it might suffice to only know it's position and orientation, since nothing else will be discernible anyways.

To use this technique we must learn about something called [**archetypes**](/2.3/manual/advanced-topics/schema-explained/archetypes).

## Levels of Detail

Any Prefab with the **CoherenceSync** component can be optimized to use a various levels of details (LODs).

There **must** always exist a LOD 0, this is the default level and it always has all components enabled (it can have per-field overrides though, see below.)

<figure><img src="/files/2Xm71cfuADuFrvsolenS" alt=""><figcaption></figcaption></figure>

There can be any number of subsequent LODs (e.g. LOD 1, LOD 2, etc.) and each one must have a distance threshold higher than the previous one. The **coherence** SDK will try to use the LOD with the highest number, but that is still within the distance threshold.

{% hint style="success" %}
**Example**

An object has three LODs, like this:

* LOD 0 (threshold 0)
* LOD 1 (threshold 10)
* LOD 2 (threshold 20)

If this object is 15 units away, it will use LOD 1.
{% endhint %}

{% hint style="warning" %}
Confusingly, the highest numbered LOD is usually called the *lowest* one, since it has the least detail.
{% endhint %}

On each LOD, there are **two options** for optimizing data being transferred:

1. Components can be turned off, meaning you won't receive **any** updates from them.
2. Its fields can be configured to use fewer bits, usually leading to less fine-grained information. The idea is that this won't be noticeable at the distance of the LOD.

## Bits and range

**coherence** allows us to define the range of numeric fields and how many bits we want to allocate to them.

Here are some terms we will be using:

* **Bits**. The number of bits (octets) used for the field. When used for vectors, the number defined the number of bits used for each component (`x`, `y` and `z`). A `vector3` set to `24 bits` will consume `3 * 24 = 72` bits.
* **Range.** For integer values and fixed-point floats, we define a minimum and maximum possible value (e.g. `Health` can lie between `0` and `100`).

{% hint style="info" %}
More bits mean more precision. Increasing the range while leaving the bit count the same will lower the precision of the field.
{% endhint %}

{% hint style="warning" %}
The maximum number of bits used for any field/component is currently 32.
{% endhint %}

**coherence** allows us to define these values for specific components and fields. Furthermore, we can define levels of detail so that precision and therefore bandwidth consumption falls with the distance of the object to the point of observation.

{% hint style="info" %}
Levels of detail are calculated from the distance between the entity and the center of the LiveQuery.
{% endhint %}

## Defining levels of detail

On each LOD you can configure the individual fields of any component to use less data. You can only decrease the fidelity, so a field can't use more data on a lower (more far away) LOD. The Archetype editor interface will help you to follow these rules.

In order to define levels of detail, we have to click the *Optimize button* on a Prefab's `CoherenceSync` component with defined field bindings.

<figure><img src="/files/BQwWk996uM2gKe4dLszq" alt=""><figcaption></figcaption></figure>

That opens the *Optimization* window. We can override the base component settings even without defining further levels of detail.

Clicking on *Add new Level Of Detail* will add a new LOD. We can now define the **distance at which the LOD starts**. This is the minimum distance between the entity and the center of the LiveQuery at which the new level of detail becomes active (i.e. the Replicator will start sending data as defined here at this distance).

![](/files/-MYklc4cS2H6HycoiFSS)

You can also **disable** components at later LOD levels if they are not needed. In the example above, you can see that in LOD2 the entire *Transform* and *Animator components* are disabled beyond the distance of 20 units. At 100 units (a.k.a. meters), we usually do not see animation details, so we can save a lot of bandwidth and processing power by not replicating this data.

The **Data Cost Overview** shows us that this takes the original 913 bits down to just 372 bits at LOD level 2.

<figure><img src="/files/Msw8Xqwt6I9lAjveBZIN" alt=""><figcaption></figcaption></figure>

## Field overrides per type

The primitive types that coherence supports can be configured in different ways:

### Float, Vector2 & Vector3

These three types can all be configured in the same way, using different compression types:

**None**

No compression will be used, a full 32-bit float will be transmitted every time.

**Truncated**

Allows for specifying the number of bits for compression. Less bits means lower bandwidth usage but at the cost of precision loss. The minimum number of bits is 10. Using 22 bits will result in around half of the precision of the full float, while 16 will result in the quarter of the precision.

**Fixed point**

Allows for specifying the range of values used together with either number of bits or a desired precision.

* Range affects the maximum and minimum value that the data type can take on. For example, a range of 100 to 200 means only values within that range can be sent - any value outside of this range will be clamped to the nearest correct value.
* Precision defines the greatest deviation allowed for the data type. For example, a precision of 0.1 means that a float of value 10.0 can be transmitted as anything from 9.9 to 10.1 over the network. The minimum allowed precision is 0.1, while the maximum precision depends on the range. Changing precision automatically recalculates the number of bits required for given range.
* Bits dictate how many bits to use when calculating the precision for a given range. When set manually, it will trigger recalculation of the precision for a given range. Mind that the number of bits can be rounded down if the calculated precision uses less, e.g. for a range of \[0, 1] setting the number of bits to 6 will result in precision of 0.1 and a final bit count of 4, since 4 bits suffice to represent this range with a calculated precision.

{% hint style="warning" %}
When using these range settings for vectors, it affects each axis of the vector separately. Imagine shrinking its bounding box, rather than a sphere.
{% endhint %}

### Integers

Integers can be configured to any span (that fits within a 32-bit integer) by setting its minimum and maximum value.

For example, the member variable `age` in a game about ancient trolls might use a minimum of 100 and a maximum of 2000. Based on the size of the range (1900 in this case) a bit-count will be calculated for you.

{% hint style="danger" %}
For integers, it usually make sense to not decrease the range on lower LODs since it will overflow (and wrap-around) any member on an entity that switches to a lower LOD. Instead, use this setting on LOD 0 to save data for the whole Archetype.
{% endhint %}

### Quaternions & Colors

Quaternions and Colors can be configured using the number of bits per component. Quaternions require sending 3 components while Colors require 4 components.

### Other types

All other types (strings, booleans, entity references) have no settings that can be overridden, so your only option for optimizing those are to turn them off completely at lower LODs.

## Using LODs with connected entities

If a LODed game object is parented to another synced object, the child will base its LOD level on the World position of its parent. This means that the (local) position of the LODed child does not have any effect on its LOD, until it is unparented.

Also – to save bandwidth, detection of LOD changes on the client only happens when the entity sends a component update. This means that a child object might appear to be using a nonsensical LOD until it changes in some way, for example by modifying its position.

## LODs in the schema

When we bake, information from the `CoherenceArchetype` component gets written into our schema. Below, you can see the setup presented earlier reflected in the resulting schema file.

```
archetype FemZombie
  lod 0
    WorldPosition 
      value [compression "FixedPoint", range-min "-2400", range-max "2400", bits "19", precision "0.01"]
    WorldOrientation 
      value [bits "24"]
    FemZombie_UnityEngine_Animator 
      InputHorizontal [compression "FixedPoint", range-min "-1", range-max "1", bits "15", precision "0.0001"]
      InputVertical [compression "FixedPoint", range-min "-1", range-max "1", bits "15", precision "0.0001"]
      InputMagnitude [compression "FixedPoint", range-min "-1", range-max "1", bits "15", precision "0.0001"]
      TurnOnSpotDirection [compression "FixedPoint", range-min "-1", range-max "1", bits "15", precision "0.0001"]
      ActionState [bits "15", range-min "0", range-max "10"]
  lod 1 [distance "50"]
    WorldPosition 
      value [compression "FixedPoint", range-min "-2400", range-max "2400", bits "16", precision "0.1"]
    WorldOrientation 
      value [bits "20"]
    FemZombie_UnityEngine_Animator 
      InputHorizontal [compression "FixedPoint", range-min "-1", range-max "1", bits "15", precision "0.0001"]
      InputVertical [compression "FixedPoint", range-min "-1", range-max "1", bits "15", precision "0.0001"]
      InputMagnitude [compression "FixedPoint", range-min "-1", range-max "1", bits "15", precision "0.0001"]
      TurnOnSpotDirection [compression "FixedPoint", range-min "-1", range-max "1", bits "15", precision "0.0001"]
      ActionState [bits "15", range-min "0", range-max "10"]
      IdleRandom [bits "15", range-min "-9999", range-max "-9999"]
      RandomAttack [bits "15", range-min "-9999", range-max "-9999"]
      AttackID [bits "15", range-min "-9999", range-max "-9999"]
      DefenseID [bits "15", range-min "-9999", range-max "-9999"]
      RecoilID [bits "15", range-min "-9999", range-max "-9999"]
      ReactionID [bits "15", range-min "-9999", range-max "-9999"]
      HitDirection [bits "15", range-min "-9999", range-max "-9999"]
  lod 2 [distance "100"]
    WorldPosition 
      value [compression "FixedPoint", range-min "-2400", range-max "2400", bits "16", precision "0.1"]
    WorldOrientation 
      value [bits "16"]
```

{% hint style="info" %}
If you want to know more about how LODs work inside the schema files, take a look at [Archetypes](/2.3/manual/advanced-topics/schema-explained/archetypes).
{% endhint %}

## Caveats

The most unintuitive thing about archetypes and LOD-ing is that it doesn't affect the *sending* of data. This means that a "fat" object with tons of fields will still tax the network and the Replication Server if it is constantly updated, even if it uses a very optimized Archetype.

Also, it's important to realize that the exact LOD used on an entity varies for each other client, depending on the position of their query (or the closest one, if several are used.)


# Profiling

#### Overview

An integration with the Unity Profiler provides basic statistics on networking events and bandwidth.

{% hint style="info" %}
The module is only available in Unity 2021.2 and newer.
{% endhint %}

<figure><img src="/files/GX8LoX8H7VT00zeyEOgE" alt=""><figcaption><p>Unity Profiler with Coherence module</p></figcaption></figure>

#### Usage

To view the module, open the Unity Profiler by selecting *Window > Analysis > Profiler*.\
Open the *Profiler Modules* dropdown menu in the top left, and select the *coherence* module.

<figure><img src="/files/Iz2bmTy84D9A9iS1F3hS" alt=""><figcaption><p>Profiler Modules dropdown menu</p></figcaption></figure>

To hide unneeded graph lines, select the colored square next to the item you do not wish to see.


# Simulation frequency

Without a special configuration, Entity data is captured at the highest possible frequency and sent to the Replication Server. This often generates more data than is needed to efficiently replicate the Entity's state across the network.

### Global simulator frequency

On a Simulator, we can limit the framerate globally using Unity's built-in static variable *targetFrameRate*.

```csharp
Application.targetFrameRate = 10;
```

{% hint style="info" %}
**coherence** will automatically limit the target framerate of uploaded Simulators to **30 frames per second**. We plan to make it possible to lift this restriction in the future. Check back for updates in the next couple of releases.
{% endhint %}

### Per-binding sampling frequency

Replication frequency can be configured for each binding individually in the Prefab Optimize window. The **Sample Rate** controls how many times per second values are sampled and synced over the network.

{% hint style="info" %}
Since the default packet send frequency of the Replication Server is 20Hz, sample rates above that value won't have any benefits unless you increase the Replication Server send frequency, too. See here how to [adjust the Replication Server send frequency](/2.3/manual/replication-server#adjusting-send-and-receive-frequencies).
{% endhint %}

![Use the Sample Rate to keep down bandwidth costs when scaling up.](/files/rchOSebjZDSEdF9jNtSm)

High sample rates increase replication accuracy and reduce latency, but consume more bandwidth. The upper limit at which samples can be quantized is 60hz, so sample rates beyond that are generally not recommended. It is not possible to change sampling frequency at runtime.

{% hint style="info" %}
Values that don't change over time do not consume any bandwidth. Only bindings with updated values will be synced over the network.
{% endhint %}


# Networking voice

coherence offers realtime voice networking through a proven solution: [Dissonance Voice](https://placeholder-software.co.uk/dissonance/) by [Placeholder Software](https://placeholder-software.co.uk/). It can be obtained through the [Asset Store](https://assetstore.unity.com/packages/slug/70078).

<figure><img src="/files/fOtJV6pHjWZYuAUWMSwY" alt=""><figcaption><p>You can find the coherence + Dissonance integration within <code>coherence > Hub > Samples</code>.</p></figcaption></figure>

{% hint style="info" %}
You need a copy of Dissonance on your project for this integration to work.
{% endhint %}

{% hint style="success" %}
In the future, there might be other voice integrations available. If you'd like to see support for a solution you're fond of, reach out to us!
{% endhint %}

Once imported, `Assets/Dissonance/Integrations/Coherence` contains the integration and a demo scene.

Here's a breakdown of the components this integration offers. [Further down](#setup-from-scratch) we walk through a practical setup.

<table><thead><tr><th width="255">Class / Unity Component</th><th>What it does</th><th>How to use it</th></tr></thead><tbody><tr><td>CoherenceCommsNetwork</td><td>The core of the integration. Runs Dissonance as Server+Client (Host) or Client. To decide in which mode to run, it relies on <a href="/pages/-MYOi6cWDwyVugtmxDuv">authority</a>.</td><td>Create a networked prefab with this component attached. Whoever has authority over it, will be the server.</td></tr><tr><td>CoherenceSyncVoice</td><td>Defines the networked entity associated with each client. To do this, it relies on <a href="/pages/-MdqtfJ7ZOJFwqweQTb1">Client Connections</a>.</td><td>Create a networked prefab with this component attached, and reference it as a Client Connection Prefab on your CoherenceBridge. Each client on the network will send data to the server through this entity.</td></tr><tr><td>CoherencePlayer</td><td>Implements a <a href="https://placeholder-software.co.uk/dissonance/docs/Tutorials/Custom-Position-Tracking.html#how-dissonance-tracks-players">Dissonance Player</a>, used for 3D and proximity audio processing.</td><td>Add to your networked player.</td></tr></tbody></table>

The demo project, found in `Assets/Dissonance/Integrations/Coherence/Demo` , showcases how all these pieces work in conjunction. The scene `Demo` describes within the hierarchy each of the pieces.

<figure><img src="/files/SGllzI9CEQ9enKvvcXFQ" alt=""><figcaption></figcaption></figure>

## Setup from scratch

If you prefer to set up voice networking from scratch, here's how to do it. You will need:

* A networked prefab that acts as the server
* A networked prefab that acts as the client
* (Optional) if you want proximity-based voice, a Networked Prefab that acts as the player

### Server (via CoherenceCommsNetwork)

Create a GameObject and attach CoherenceCommsNetwork to it. This automatically adds CoherenceSync and DissonanceComms.

Now, convert it into a prefab. You can do this by clicking on the *Sync with coherence* header, through the CoherenceSync inspector, or just by dragging it somewhere from the Hierarchy window into the Project window.

This prefab will represent our voice server. Keep it on the scene, or instantiate it at the time you want to start the Dissonance voice network.

On the CoherenceSync component, change the Lifetime to Persistent, and enable Auto-adopt Orphan. This allows the voice server to be adopted by someone else if the host disconnects.

{% hint style="success" %}
In the demo content, this Prefab is called `Coherence Dissonance Comms` .
{% endhint %}

### Client (via CoherenceSyncVoice)

Create a GameObject and attach CoherenceSyncVoice to it. This automatically adds CoherenceSync.

Now, convert it into a prefab. You can do this by clicking on the *Sync with coherence* header, through the CoherenceSync inspector, or just by dragging it somewhere from the Hierarchy window into the Project window.

This Prefab will represent our voice client. Don't instantiate this yourself. Instead, reference it on your [CoherenceBridge](/2.3/manual/components/coherence-bridge) component as a client connection prefab.

<figure><img src="/files/7JeLrKXLnN3wrhguT3Zi" alt=""><figcaption><p>Fix any problems when referencing a client connection prefab. In this case, it's suggesting to disable authority transfer, since that's not supported by <a href="/pages/-MdqtfJ7ZOJFwqweQTb1">Client Connections</a> (Client Connections are a special kind of entity, handled by the Replication Server).</p></figcaption></figure>

{% hint style="success" %}
In the demo content, this prefab is called `Coherence Sync Voice` .
{% endhint %}

### Player (via CoherencePlayer)

Attach CoherencePlayer to the root of your player prefab, which should be a networked prefab.

If your player isn't networked yet, attaching this component will also attach a CoherenceSync.

This Prefab will now report position to Dissonance, to allow proximity-based voice.

{% hint style="success" %}
In the demo content, this prefab is called `Coherence Player` .
{% endhint %}

### Voice Triggers

You will need [Voice Broadcast Trigger](https://placeholder-software.co.uk/dissonance/docs/Reference/Components/Voice-Broadcast-Trigger.html) (when and where voice is sent to) and [Voice Receive Trigger](https://placeholder-software.co.uk/dissonance/docs/Reference/Components/Voice-Receipt-Trigger.html) (what we listen to) components.

### That's all folks

From here on, you can start to experiment with voice. Make sure to keep reading through [Dissonance's Documentation](https://placeholder-software.co.uk/dissonance/docs/) for further insights into voice support.


# Settings

Accessible via `coherence > Settings` and `Edit > Project Settings... > coherence`.

<figure><img src="/files/jTYq8lCr5Loe4dMEIbA8" alt=""><figcaption><p>Settings have descriptive tooltips that help understand what they do.</p></figcaption></figure>


# 1 game instance <-> N connections

In some cases, you might want your game to create multiple individual connections within the same game instance. This could be the case when you want to support [split-screen scenarios](#user-content-fn-1)[^1], or to create development environments (interpolation visualization, stress-testing, debug network scenarios, quick prototyping within the Editor, etc.).

To understand how to achieve this, it's important you understand how **coherence** establishes a connection.

## What Makes a Network Connection

[CoherenceBridge](/2.3/manual/components/coherence-bridge) is the core component that handles a network connection with coherence. This component is responsible of establishing the connection, and also to keep in sync [network state](#user-content-fn-2)[^2] and [scene state](#user-content-fn-3)[^3].

One CoherenceBridge is able to handle one network connection, and keep in sync the network state within one scene: the one it was instantiated on.

{% hint style="success" %}
1 CoherenceBridge = 1 network connection = 1 scene.
{% endhint %}

Knowing this crucial rule, if we want N connections, we will need N scenes, each of them with a bridge. Each bridge can establish a connection with any endpoint. So technically, a game instance can simultaneously connect to a combination of Rooms and Worlds. Including several connections to the same Rooms or Worlds, as it would be the case for a split-screen setup.

You can create this scenario by your own means. However, we do provide a solution out-of-the-box that helps handle connections: the CoherenceSceneLoader and CoherenceScene component duo.

## Simplifying Connections: CoherenceSceneLoader & CoherenceScene

At its core, what these components orchestrate is loading scenes additively, and associate them with network connections.

<table><thead><tr><th width="209">Unity Component</th><th>Description</th></tr></thead><tbody><tr><td>CoherenceSceneLoader</td><td>Handles loading one scene additively, and holds instructions for how that loaded scene should connect to the network.</td></tr><tr><td>CoherenceScene</td><td>Reacts when the scene this component is on is loaded via CoherenceSceneLoader. When it does, establishes a connection using the <a href="/pages/vsFWvpyrMwSCjaJDzZgH">CoherenceBridge</a> on said scene. The connection data used (EndpointData) is facilitated by the CoherenceSceneLoader that triggered the scene load.</td></tr></tbody></table>

{% hint style="info" %}
One CoherenceSceneLoader can only load/unload one scene at a time. If you want to load N scenes, you will need N CoherenceSceneLoaders.
{% endhint %}

In the following section we explore a practical use case of this feature.

## Tutorial — 4 players, 1 Editor

Let's say we want to prototype a scenario where there's 4 players connected to the network. And we want to do this within one game instance (in this case, within the Editor), to serve as a very quick and rough development environment where we can observe how the network reacts to anything we throw at it.

We can achieve that with CoherenceSceneLoader and CoherenceScene.

We need a total of 3 CoherenceSceneLoaders — these will be our extra connections, so that we have a total of 4 players connecting from within our game instance.

By the end of this tutorial, we will have a setup that looks like this:

<figure><img src="/files/Sfby7B1WaMlonaWMYV5y" alt=""><figcaption></figcaption></figure>

Let's get to it. I'm starting with an empty scene that has a Camera, a [CoherenceBridge](/2.3/manual/components/coherence-bridge) and a [CoherenceLiveQuery](/2.3/manual/components/coherence-live-query).

First, let's create the CoherenceSceneLoaders on our scene. Remember, we're creating 3 of them.

<figure><img src="/files/IwFekYtOb7D4e8OGRJas" alt=""><figcaption><p>Creating a GameObject with a Scene Loader component on it</p></figcaption></figure>

<figure><img src="/files/AajRpiljtdmDGxKLRY0N" alt=""><figcaption><p>CoherenceSyncLoader Inspector</p></figcaption></figure>

Select the 3 of them, and on the Inspector:

* Enable **Attach**
* Set the **Connection Type** to **Client**
* Set the **Scene Name** to the name of the current scene (if it's not already)

<figure><img src="/files/hQfxe9RTkJqpT0XkH3jU" alt=""><figcaption><p>Values set on the Inspector, as described above</p></figcaption></figure>

Let's break down why we're doing this:

In this example, we're going to be loading the same scene we're already working on, 3 additional times (one time per CoherenceSceneLoader component). We set Scene Name accordingly (in this case, it's **Main**).

This is, however, not the only way you can think of setting this environment up. A different approach could be to have 4 CoherenceSceneLoaders, and start from a **Menu** scene. But in this example I didn't go that route — we're working with our only scene.

{% hint style="info" %}
Make sure the scene you're working on is part of the Build Profile's Scene List.
{% endhint %}

With this setup, every time this scene connects to the network, 3 additional scenes will be additively loaded and connected (as Clients, as specified in the Connection Type) to the same space (room or world), meaning there will be a total of 4 players coexisting.

We change the connection type to Client since we're not going to be using [Simulators](/2.3/manual/simulation-server) for this example.

I'm going to use the **Rooms Connect Dialog** to not care about the connection logic. You can find it in the **Samples** tab in the Hub (**coherence > Hub**).

<figure><img src="/files/kjrvdc6qrNhRnY5RPYYC" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
At this point, make sure your baked data is up-to-date.

If using coherence Cloud, make sure the schemas are uploaded.\
You can do this from the Hub (**coherence > Hub** menu item).

If using a local Replication Server, make sure it's stopped/started after baking, so it uses the latest generated schema. You can start a local Replication Server from the Hub as well.
{% endhint %}

Enter Play Mode and connect to coherence using the in-game connection dialog. When creating the room, make sure **Max Players** is set to **4 or more** (default is 10).

Once connected to the room (i.e., the CoherenceBridge establishes connection), the 3 CoherenceSceneLoaders will trigger — as they are **attached** to the scene's CoherenceBridge — and load 3 additional scenes, that will automatically connect to the network as well.

<figure><img src="/files/PsBVTR0pUsXs4Tgkk2DC" alt=""><figcaption><p>Hierarchy after entering the room — 4 client connections established!</p></figcaption></figure>

You can click on the Unity icon at the right side of the GameObject, in the Hierarchy Window, to ping which CoherenceScene is associated with each CoherenceSceneLoader.

<figure><img src="/files/GEo8nlrzgjuh6SgxxEyh" alt=""><figcaption><p>Clicking on the Unity icon on CoherenceScene or CoherenceSceneLoader pings its counterpart</p></figcaption></figure>

The 3 CoherenceSceneLoaders are reacting to the CoherenceBridge getting connected/disconnected. This is because they are **attached** to CoherenceBridge. If we didn't attach, we'd need to manually call `CoherenceSceneLoader.Load(EndpointData)` and pass the data needed to perform the operation.

Notice also how the CoherenceScene component has been automatically added for us on each of the loaded scenes. Warnings will appear on the Console window, telling us that a CoherenceScene has been created on-the-fly.

We want to control what happens when we load a scene via CoherenceSceneLoader, so creating a CoherenceScene on our own, and configuring it our way, is what we should do next.

Let's exit Play Mode and add a CoherenceScene:

<figure><img src="/files/sLQiWYncZG1vn8EB0gRI" alt=""><figcaption><p><code>GameObject > coherence > Scene (Listener)</code></p></figcaption></figure>

<figure><img src="/files/dQvvHAKYoGCb30D8k0CL" alt=""><figcaption><p>CoherenceScene Inspector</p></figcaption></figure>

By default, this component will try to establish a connection once loaded (**Connect** toggle is on), and also handles reconnects out-of-the-box.

What's interesting for us at this point though, is disabling some logic from the scenes after they are loaded. Specifically, we want the Camera, the EventSystem and the Connection Dialog on the loaded scenes to be disabled, so that they don't interfere with the ones present in the main scene.

CoherenceScene provides a handy **Deactivate On Load** list that you can use for this matter, but you can also use the On Loaded event to script any logic you might want.

The Deactive On Load list also comes with a **Smart Select** button, that selects GameObjects found that are generally good candidates to be disabled when working with this feature.

By clicking on it, Camera and EventSystem are populated, and will be disabled after the scene is loaded. We also want to disable the Rooms Connection Dialog, so we reference it there manually.

<figure><img src="/files/Iv28kJXLWdil6aFp3jGq" alt=""><figcaption></figcaption></figure>

Let's save the changes and see what's happening now once we enter Play Mode.

1. Via the in-game Connection Dialog, create or join a room.
2. Once joined, notice the [4 active connections](#user-content-fn-4)[^4] on the **Hierarchy** window.
3. Now, click on the **Disconnect** button of the Connection Dialog — it should be clickable after we've disabled the EventSystems, Cameras and Connection Dialogs from the additional scenes.\
   ![](/files/rrKfWpZZSAbds97JuNQl)
4. After disconnecting, you'll notice the other 3 connection have also disappeared — attaching loads **and also unloads** when, CoherenceBridge connects/disconnects.

So far we haven't seen anything being networked. So that's what we're going to do next.

Let's create a Cube and network it.

<figure><img src="/files/zb06C3mnocSPzgmpuEqK" alt=""><figcaption><p>Let's create a Cube</p></figcaption></figure>

<figure><img src="/files/4va3sLyVXVN6141BIVWS" alt=""><figcaption><p>Cube created, now let's network it by clicking <strong>Sync with coherence</strong> on the Inspector.</p></figcaption></figure>

<figure><img src="/files/WYEmNsZDeIdZla5nk9QG" alt=""><figcaption><p>All set! Our Cube is now networkable. It's also part of the scene right now.</p></figcaption></figure>

{% hint style="warning" %}
At this point, make sure you bake, upload schemas and or (re)start the Replication Server, given we've created a new Networkable Prefab. You can do this from within the Hub, from the **coherence menu**, or from the icon shown in the **Project** window, next to the `Assets/coherence` folder.
{% endhint %}

Now, let's enter Play Mode again.

<figure><img src="/files/C8nFkkrozFnLSwYpUAs0" alt=""><figcaption></figcaption></figure>

We now see 4 cubes — one per connection. You can differentiate which one you have authority over, and which ones are the replicated ones (solid coherence logo represents authority, outlined coherence logo represents non-authority / remote).

Now, let's spice it up — let's use this setup to **visualize interpolation at runtime**.

1. Create two materials. We will use these to differentiate authority and remote. I'll be using red and green.

<figure><img src="/files/xN0mr1HzhtvAe7WqCjTx" alt=""><figcaption></figcaption></figure>

2. Next, let's assign apply these materials on our Cube, based on authority.
3. Go to the Cube Prefab, and hit **Configure** on the **CoherenceSync Inspector**.
4. Once there, click the **Components tab**.

<figure><img src="/files/7KQUqmLKrHPskL9XCn2N" alt=""><figcaption></figcaption></figure>

5. Open the **Action** dropdown, under **Mesh Renderer**, and select **Handle Material**:

<figure><img src="/files/lzhWxXuERzLpAg9oXW8U" alt=""><figcaption></figcaption></figure>

6. Use our previously created materials, as such:

<figure><img src="/files/QznF1Ev9EzzQIWlmYQTv" alt=""><figcaption></figcaption></figure>

We're almost there. Let's enter Play Mode again.

Once connected, select a Cube you [have authority over](#user-content-fn-5)[^5] from any of the loaded scenes.

<figure><img src="/files/IwLWsgm9bTznwCI5FxU7" alt=""><figcaption><p>Keep the Scene view active, we will use it to visualize what's going on</p></figcaption></figure>

Drag that Cube around, so that it doesn't overlap with the other (replicated) Cubes.

Do you see those eye icons on the scene headers, on the Hierarchy window? They control what your Scene window is rendering. While the Cube you dragged is selected, let's visualize what's happening on the other connections. Enable rendering on any of the other scenes:

<figure><img src="/files/KzS4yxVEaOimwwT7b0cs" alt=""><figcaption></figcaption></figure>

Now, drag the Cube again. Do you see a red Cube following it along? That's the replicated copy, catching up and being interpolated!

<figure><img src="/files/5Fsy62ersghg3nnhy53G" alt=""><figcaption></figcaption></figure>

Now you can try out how interpolation behaves when using different settings.

<figure><img src="/files/Ahn13cl3d32lKAWJG0cn" alt=""><figcaption></figcaption></figure>

Now you have a sandbox you can use to toy around with. Drag and drop Networked Prefabs on the scene, delete them, change authority on-the-fly... and all of that within one Scene view, with the debugging advantages that it brings.

If you've made it all the way here, congratulations! Now you grasp the basics needed to leverage CoherenceSceneLoader / CoherenceScene to create multiple connections within one game instance.

One final note — building a game where different connections coexist on the same build can be challenging, and requires strict rules on which scene can access what. Static access (GameManager and other singletons), physics, graceful error handling...

While this feature is powerful to provide quick development scenarios, it's not necessarily a good foundational feature to build upon to playtest a game itself. For that, we recommend you to either make builds, use Unity's Multiplayer Play Mode or ParrelSync. Read more about our recommendations on [how to test your game locally](/2.3/getting-started/setup-a-project/local-development).

[^1]: Multiple Connections within a game instance is not the only way to solve this. You might want to simplify the problem by having your one connection handle multiple players.

[^2]: what the Replication Server sees

[^3]: what Unity sees

[^4]: 4 `Main` scenes loaded, 3 of them loaded via CoherenceSceneLoader. All of them connected to the same room.

[^5]: The one with the coherence **solid logo** on the Hierarchy window.


# Scene management

Scenes or levels are a common feature of Unity games. They can be loaded from Unity scenes, custom level formats, or even be procedurally generated. In networked games, players should not be able to see entities that are in other scenes. To address this, coherence's scene feature gives you a simple way of controlling what scene you're acting in.

Each Coherence scene is represented by an integer index. You can map this index to your scenes or levels in any way you find appropriate. Projects that don't use scenes will implicitly put all their entities into scene 0.

### Keeping a connection alive between Scene changes

Since the connection to the Replication Server is done through the [CoherenceBridge](/2.3/manual/components/coherence-bridge) component, it means that if you switch Scenes, the current CoherenceBridge that holds the connection to the Replication Server will be destroyed.

In order to keep a CoherenceBridge with its connection alive between Scene changes, you will have to set it as **Main Bridge** in the Component inspector:

<figure><img src="/files/ckM1dYmKWFN6ucMyTur6" alt=""><figcaption><p>CoherenceBridge Inspector</p></figcaption></figure>

{% hint style="info" %}
If this approach to keeping the connection alive is not a good fit for your game, see [Custom Setup](#custom-setup) in the second part of this document.
{% endhint %}

### Automating Scene transitions

In the CoherenceBridge inspector you will find all the options related to handling Scene transitions. First thing to know is that [Client Connections](/2.3/manual/client-connections) must be enabled for this feature to work.

These are the options related to Scene transitions:

* ***Main Bridge*****:** This CoherenceBridge instance will be saved as DontDestroyOnLoad and its connection to the Replication Server will be kept alive between Scene changes. All other CoherenceBridge components that are instantiated from this point forward will update the target Scene of the Main Bridge, and destroy themselves afterwards.
* ***Use Build Index as Scene Id*****:** Every Scene needs a unique identifier over the network. This option will automate the creation of this ID by using the Scene Build Index (from the *Build Settings* window).
* ***Scene Identifier*****:** If the previous option is unchecked, then you will be able to manually set a Scene Identifier of your own (restricted to unsigned integers).

{% hint style="info" %}
Using these options will **automate Scene transitions**.

The only **requirement** is having **a** **single CoherenceBridge set as Main** (the first one that your game will load). The rest of the Scenes you want to network should also have a **CoherenceBridge component**, but **not** set as main.

This option requires no extra code on your part.
{% endhint %}

### Considerations on entity Authority

All the entities that Client has authority over are always kept in the same coherence scene. Clients cannot have authority over entities in other scenes. This implies a few things:

1. When a Client changes scene, it will bring along any entities it has authority over.
2. If an entity changes owner via [Authority transfer](/2.3/manual/networking-state-changes/authority/authority-transfer), it will be moved to the new owner's scene.
3. To avoid an entity moving with a Client, the owner has to relinquish authority by using `AbandonAuthority()`, and then they can move scenes. These Orphaned[^1] entities will stay in the scene where their previous owner left them.

{% hint style="success" %}
[ClientConnections](/2.3/manual/client-connections) are visible even for clients in different scenes. It's possible to check which scene they are in using the `Scene` property.
{% endhint %}

### Implicit destruction of entities when loading Unity scenes

Note that Unity will destroy all game objects not marked as `DontDestroyOnLoad` whenever a new Unity scene is loaded (non-additively). If the client has authority over any of those entities at that point, coherence will replicate that destruction to all other clients. If that is undesirable and you need to leave entities behind, make sure that authority has been lost or transferred before loading the new Unity scene. You can of course also mark them as `DontDestroyOnLoad`, which will bring them along to then new scene.

Since this process involves a bit of logic that has to be executed over several frames, coherence provides a `LoadScene` helper method (co-routine) on `CoherenceSceneManager`. Here's an example of how to use it:

```csharp
private IEnumerator LoadNextScene()
{
    CoherenceSync[] bringAlong = new CoherenceSync[] { sword, torch, rope };
    yield return CoherenceSceneManager.LoadScene(bridge, ++sceneIndex, bringAlong);
}
```

### Limitations

It is not possible to move entities to other scenes without the client connection also moving there. Additionally, you can't currently query for entities in other scenes.

Both of these limitations are planned to be addressed in future versions of **coherence**.

### Custom setup

If your project isn't a good fit for the automatic scene transitioning support described above, it is possible to use a more manual approach. There are a few important things to take care of in such a setup:

If you ever load another Unity scene, the `CoherenceBridge` that connects to the server needs to be kept alive, or else the client will be disconnected. A straightforward way of doing this is to call Unity's `DontDestroyOnLoad` method on it. This creates two problems when replicating entities from other Clients:

1. **The bridge instantiates remote entities into the scene where it is currently located.** To override this behaviour, set the `InstantiationScene` property on your `CoherenceBridge` to the desired scene.
2. **Any new CoherenceSync instances will look for the bridge in the same scene that they are located.** If the bridge is moved to the `DontDestroyOnLoad` scene, this lookup will fail. You can use the static `CoherenceSync.BridgeResolve` event to solve this problem (see the code sample in the next section). Alternatively, if you have a reference to a Scene, you can register the appropriate bridge for entities in that scene with `CoherenceBridgeStore.RegisterBridge` **before** it is loaded.

Additionally, **coherence** queries (e.g. `CoherenceLiveQuery`) also look for their bridge in their own scene, so you might have to set its `bridgeResolve` event too.

{% hint style="info" %}
If you load levels via your own level format, or by loading Unity scenes additively, it is quite possible that you can skip some of the steps above.

The only thing strictly necessary for coherence scene support is to call

`CoherenceBridge.SceneManager.SetClientScene(uint sceneIndex);`

so that the Replication Server knows in which scene each Client is located.
{% endhint %}

#### Code sample

Here's a complete code sample of how to use all the above things together:

```csharp
using UnityEngine;
using UnityEngine.SceneManagement;
using Coherence.Toolkit;

public class Example : MonoBehaviour
{
    public CoherenceBridge bridge;
    public CoherenceLiveQuery query;

    void Awake()
    {
        // Move the bridge to DontDestroyOnLoad but still
        // instantiate into the active scene
        var scene = bridge.gameObject.scene;
        DontDestroyOnLoad(bridge);
        bridge.InstantiationScene = scene;

        // Make the query find the bridge
        query.BridgeResolve += _ => bridge;

        // Make new CoherenceSync:s find the bridge
        CoherenceSync.BridgeResolve += _ => bridge;

        // Get notified if the scene is changed
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        // Moves the client connection to another scene on the server
        bridge.SceneManager.SetClientScene(scene.buildIndex);

        // Instantiate remote entities into the new scene instead
        bridge.InstantiationScene = scene;
    }
}
```

[^1]: An entity that no-one has authority over. See [Orphans](/2.3/support/glossary#orphans).


# Simulators

**coherence** uses the concept of authority to determine who is responsible for simulating each Entity. By default, each Client that connects to the Replication Server owns and simulates the Entities they create. There are a lot of situations where this setup is not adequate. For example:

* The number of Entities could be too large to be simulated by the players on their own, especially if there are few players and the World is very large.
* The game might have an advanced AI that requires a lot of coordination, which makes it hard to split up the work between Clients.
* It is often desirable to have an authoritative object that ensures a single source of truth for certain data. State replication and "eventual correctness" doesn't give us these guarantees.
* Perhaps the game should run a persistent simulation, even while no one is playing.

With **coherence**, all of these situations can be solved using dedicated *Simulators*. They behave very much like normal Clients, except they run on their own with no player involved. Usually, they also have special code that only they run (and not the clients). It is up to the game developer to create and run these programs somewhere in the cloud, based on the demands of their particular game.

{% hint style="info" %}
Simulators can also be independent from the game code. A Simulator could be a standalone application written in any language, including **C#,** **Go** or **C++**, for instance. We will post more information about how to achieve this here in the future. For now, if you would like to create a Simulator outside of Unity, please [contact our developer relations team](mailto:devrel@coherence.io).
{% endhint %}

{% hint style="warning" %}
To use Simulators, you need to enter your credit card details. You can do it by logging into the [Dashboard](https://coherence.io/dashboard), selecting the *Billing and Plans* tab, finding the *Payment Methods* section and clicking the *Manage* button.

If you're on the Free plan, you won't be charged anything - our payment provider will *temporarily* reserve a small amount to verify that the credit card is in working order.
{% endhint %}

{% hint style="warning" %}
Only **Paid** and **Enterprise** plans offer Simulators external network connectivity.\
When switching from Free plan to a Paid or Enterprise plan, it may take up to **10 minutes** for the Simulators to have their external connectivity enabled.
{% endhint %}

## Creating a Simulator

If you have determined that you need one or more Simulator for your game, there are multiple ways you can go about implementing these. You could create a separate Unity project and write the specific code for the Simulator there (while making sure you use the same schema as your original project).

An easier way is to use your existing Unity project and modify it in a way so that it can be started either as a normal Client, *or* as a Simulator. This will ensure that you maximize code sharing between Clients and Servers - they both do simulation of Entities in the same Game World after all.

To force a build to start as a Simulator, you can use the following command line argument:

```
$ ./Game --coherence-simulation-server
```

## Simulators in coherence Cloud

The Simulator is started with the following parameters in coherence Cloud:

```
--coherence-region             // region where the simulator is started
--coherence-world-id           // unique world id (in world mode)
--coherence-http-server-port   // REST access for starting / stopping rooms
--coherence-auth-token         // token to authorize access
--coherence-simulation-server  // identify as simulation server
--coherence-simulator-type     // Room or World

// the following should be used also when starting a local simulation server to 
// successfully connect to the local replication server

--coherence-ip                 // address of the replication server (eg 127.0.0.1)
--coherence-port               // port of the replication server
--coherence-room-id            // room id when connecting to a room
--coherence-unique-room-id     // unique room id to connect to in room mode
--coherence-room-tags          // tags used when creating the room
--coherence-room-kv            // key values supplied when creating the room

```

{% hint style="info" %}
Important: if you want to deploy Simulators on the coherence Cloud, they have to be built for Linux 64-bit.
{% endhint %}

## SimulatorUtility

The SDK provides a static helper class to access all the above parameters in the C# code called `SimulatorUtility`.

<pre class="language-csharp"><code class="lang-csharp">static class SimulatorUtility
{
    public enum Type
    {
        Undefined = 0,
        World = 1,
        Rooms = 2
    }
    
    public static Type SimulatorType;         // Type of simulator: Room / World.
    public string Region;                     // Region where simulator was spawned.
    public string Ip;                         // Ip of the replication server.
    public int Port;                          // UDP port of the replication server.
    public int RoomId;                        // RoomId for current session. 
    public ulong UniqueRoomId;                // Unique RoomId.
    public ulong WorldId;                     // World Id (in worlds mode).
    public int HttpServerPort;                // Port used for REST commands.
    public string AuthToken;                  // Auth token used for authentication.
    public List&#x3C;string> RoomTags;             // Tags for the room. 
    public Dictionary&#x3C;string,string> RoomKV;  // Key Values for the room.
<strong>    public bool IsInvokedAsSimulator;         // Whether the instance was invoked as a simulator.
</strong>    public bool IsInvokedInCommandLine;       // Whether the instance was invoked on the commandline.
    public bool IsSimulator;                  // Identify whether simulator.  
}
</code></pre>

## Building simulators

To build Simulators, it's best to use the Linux Dedicated Server Build Target.

This is great for Simulators since we're not interested in rendering any graphics on these outside of local development. You will also get a leaner executable that is smaller and faster to be published in coherence Cloud.

When a room has only Simulators (no Clients) it shuts down automatically after a short period of time.

## Build and deploy

Refer to the [Simulator: Build and deploy section](/2.3/manual/simulation-server/build-deploy-simulators).


# Scripting: client vs simulator

When scripting Simulators, we need mechanisms to tell them apart.

### Am I a Simulator?

Ask `Coherence.SimulatorUtility.IsSimulator`.

```csharp
using Coherence;
using UnityEngine;

public class SimulatorClass : MonoBehaviour
{
    public void Awake()
    {
        if (SimulatorUtility.IsSimulator)
        {
            // I'm a simulator!
        }
    }
}
```

There are two ways you can tell **coherence** if the game build should behave as a Simulator:

* `COHERENCE_SIMULATOR` preprocessor define.
* `--coherence-simulation-server` command-line argument.

#### `Connect` and `ConnectionType`

The `Connect` method on `Coherence.Network` accepts a `ConnectionType` parameter.

```csharp
using Coherence;
using Coherence.Connection;
using Coherence.Toolkit;
using UnityEngine;

public class ConnectAsSimulator : MonoBehaviour
{
    void Start()
    {
        var endpoint = new EndpointData
        {
            region = EndpointData.LocalRegion,
            host = "127.0.0.1",
            port = 32001,
            schemaId = RuntimeSettings.instance.SchemaID,
        };

        var bridge = FindAnyObjectByType<CoherenceBridge>();
        bridge.Connect(endpoint, ConnectionType.Simulator);
    }
}
```

#### **COHERENCE\_SIMULATOR**

```csharp
#if COHERENCE_SIMULATOR

// simulator-specific code

#endif
```

Whenever the project compiles with the `COHERENCE_SIMULATOR` preprocessor define, **coherence** understands that the game will act as a Simulator.

![The custom build pipeline lets us define preprocessor defines like COHERENCE\_SIMULATOR](/files/-MYgJGldGsRlo85C5I-v)

#### **Command-line argument**

Launching the game with `--coherence-simulation-server` will let **coherence** know that the loaded instance must act as a Simulator.

{% hint style="info" %}
You can supply **additional parameters** to a Simulator that define its area of responsibility, e.g. a sector/quadrant to simulate Entities in and take authority over Entities wandering into it.

You can also build a special Simulator for AI, physics, etc.
{% endhint %}

### Server-side simulation

You can define who simulates the object in the **CoherenceSync** inspector.

![](/files/-M_LW8y2rn7vcBaXRMKc)

### **Connecting Simulators automatically to RS: AutoSimulatorConnection Component**

**coherence** includes an auto-connect MonoBehaviour out of the box for Room- and World-based Simulators. The Component its called AutoSimulatorConnection.

<figure><img src="/files/Gi1wYbcb5dW1tK1EffiW" alt=""><figcaption></figcaption></figure>

When you add the Component, it will parse the connection data passed with [Command-line arguments](/2.3/manual/simulation-server/simulator-cli-arguments) to connect to the given Replication Server automatically. This will also work for Simulators you upload to the coherence Cloud.

{% hint style="info" %}
If the Simulator is invoked with the `--coherence-play-region` parameter, **AutoSimulatorConnection** will try to reconnect to the Server located in that region.
{% endhint %}


# Run local simulators

Before deploying a Simulation Server, testing and debugging locally can significantly improve development and iteration times. There are a few ways of accomplishing this.

### Running the Editor as a Simulator

Using the Unity Editor as a Simulator allows us to easily debug the Simulator. This way we can see logs, examine the state of scenes and GameObjects and test fixes very rapidly.

To run the Editor as a Simulator, run the Editor from the command line with the proper parameters:

* `--coherence-simulation-server`: used to specify that the program should run as a **coherence** Simulator.
* `--coherence-simulator-type`: tells the Simulator what kind of connection to make with the Replication Server, can be Rooms or World.
* `--coherence-region`: tells the Simulator which region the Replication Server is running in: EU, US or local.
* `--coherence-ip`: tells the Simulator which IP it should connect to. Using 127.0.0.1 will connect the Simulator to a local server, if one is running.
* `--coherence-port`: specifies the port the Simulator will use.
* `--coherence-world-id`: specifies the World ID to connect to, used only when set to Worlds.
* `--coherence-room-id`: specifies the Room ID to connect to, used only when set to Rooms.
* `--coherence-unique-room-id`: specifies the unique Room ID to connect to, used only when set to Rooms.

For example:

```
<Editor path> -projectPath <project path>
--coherence-simulation-server 
--coherence-simulator-type rooms
--coherence-region local
--coherence-ip 127.0.0.1 
--coherence-port 32001 
--coherence-room-id [room-id]
--coherence-unique-room-id [room-uid]

```

{% hint style="info" %}
Keep in mind that **all regular Unity arguments are supported**. You can see the full list here: [Unity Editor command line arguments](https://docs.unity3d.com/Manual/EditorCommandLineArguments.html).
{% endhint %}

If you're not sure which values should be used, adding a `COHERENCE_LOG_DEBUG` define symbol will let you see detailed logs. Among them are logs that describe which IP, port and such the Client is connecting to. This can be done in the Player settings: **Project Settings > Player > Other Settings > Script Compilation > Scripting Define Symbols***.*

![](/files/bgnLrd0nWMYEtQ69aKJv)

{% hint style="info" %}
To learn more about Simulators, see [Simulators](/2.3/manual/simulation-server/client-vs-simulator-logic).
{% endhint %}

### Running a Simulator build locally from the command line

Another option is making a Simulator build and running it locally. This option emulates more closely what will happen when the Simulator is running after being uploaded.

You can run a Simulator executable build in the same way you run the Editor.

```
"simulator build path"
--coherence-simulation-server 
--coherence-ip 127.0.0.1 
--coherence-port 32001 
--coherence-world-id 0 
--coherence-room-id [room-id]
--coherence-unique-room-id [room-uid]
```

This allows you to test a Simulator build before it is uploaded or if you are having trouble debugging it.

### Running a Simulator build locally from the Unity Editor

Local simulator builds require the Dedicated Server [module to be installed](https://docs.unity3d.com/hub/manual/AddModules.html) for your version on Unity.

<figure><img src="/files/S2zmn3aeT6Z7EchC71iX" alt=""><figcaption><p>Installed modules in the Unity Hub showing Dedicated Server build support for Mac and Windows</p></figcaption></figure>

Once installed, you can create a local simulator build by clicking the '**Build Local Simulator (`target`)**' button from within the Simulator tab in coherence Hub (coherence > Hub), where `target` is the operating system on your local machine.

<figure><img src="/files/1fmMjPY6WDv5eRQfr18m" alt=""><figcaption><p>Build Local simulator button on a machine running macOS</p></figcaption></figure>

The *COHERENCE\_SIMULATOR* symbol is added during the local simulator build. Symbols can be examined in the Player Settings and can be found at **Edit > Project Settings...** in the **Player** tab under **Script Compilation**.

Local simulator builds can be run from within the coherence Hub.

<figure><img src="/files/9mP0S8tpFKntOkBYNKsU" alt=""><figcaption></figcaption></figure>

Use the **Fetch Last Endpoint** button to autofill the required fields.

### Connecting a Simulator to a Room

When using a Rooms-based setup, you first have to create a Room in the local Replication Server (e.g. by using the connect dialog in the Client).

The local Replication Server will print out the **Room ID** and **unique Room ID** that you can use when connecting the Simulator.

<figure><img src="/files/9Txq7rXdQeGRlFlmHJkY" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
To learn more about creating a Simulator build, see [SIMULATORS: Build and Deploy](/2.3/manual/simulation-server/build-deploy-simulators).
{% endhint %}


# World simulators

World Simulators are started and shut down with the World.

They can be enabled and assigned in the *Worlds* section of the *Dasboard*.

World Simulation Servers are started with the command line parameters described in the [Simulators](/2.3/manual/simulation-server#command-line-parameters-in-the-cloud) section.


# Room simulators

Simulators per room can be enabled in the dashboard for the project. The Simulator used is matched according to the [Simulator slug](/2.3/manual/simulation-server/simulator-slugs) in the RuntimeSettings scriptable object file. This is set automatically when you upload a Simulator.

<figure><img src="/files/VofzoZTE23Xu9dkRDUGY" alt=""><figcaption></figcaption></figure>

For each new Room, a Simulator will be created with the command line parameters described in the [Simulators](/2.3/manual/simulation-server#command-line-parameters-in-the-cloud) section. The Simulator is shutdown automatically when the Room is closed.


# Simulator slug

When using the *Simulators* tab in the c*oherence Hub*, you can enable the *Use Simulator* option and specify a *Simulator Slug*. This is simply a **unique identifier for a Simulator**. This value is automatically saved in `RuntimeSettings` when an upload is complete, and Room creation requests will use this value to identify which Simulator should be started alongside your room.

The Simulator slug can be any string value, but we recommend using something descriptive. If the same slug is used between two uploads, the later upload will overwrite the previous Simulator.

<figure><img src="/files/JnKv9OmzXLw69crvqJu2" alt=""><figcaption><p><em>Use the Simulators tab to specify all Simulator related settings.</em></p></figcaption></figure>

A list of uploaded Simulators can be found in the [Dashboard](https://coherence.io/dashboard), under the project's Schemas & Builds section.


# Build and deploy

### Build a Simulator to be uploaded to the cloud

A **Simulator build** is a built Unity Player for the Linux 64-bit platform that you can upload to **coherence** straight from the Unity Editor.

Open the **coherence Hub** and select the **Simulators** tab. From there you can build and upload Simulators.

### Configuring your Simulator build

You can change your Simulator build options by editing the *SimulatorBuildOptions* object, or in the **coherence Hub Simulators** ta&#x62;*.*

<figure><img src="/files/YIwlXDnFuzyGcmyB71KP" alt=""><figcaption><p>coherence Hub Simulator Build Options</p></figcaption></figure>

There are several settings you might want to change.

* Specify the scenes you want to get in the build via the **Scenes To Build** field.
* For a local build, you can choose to enable/disable the **Headless Mode** by ticking the checkbox. For a cloud build, Headless Mode is always enabled by default.
* Choose your preferred *Scripting Implementation* from the drop-down list. It can either be [Mono 2x](https://docs.unity3d.com/Manual/Mono.html) or [IL2CPP](https://docs.unity3d.com/Manual/IL2CPP.html).
* For more information about the options listed under **Build Size Optimizations**, see [this section below](#reducing-simulator-build-size-experimental).

### Create and upload the build

{% hint style="info" %}
Make sure you have completed the steps required in [Create an account](/2.3/getting-started/setup-a-project/test-in-the-cloud).
{% endhint %}

{% hint style="warning" %}
**Make sure you meet the requirements:**

1. You have to have Linux modules (`Linux Build Support (IL2CPP)`, `Linux Build Support (Mono)`, and `Linux Dedicated Server Build Support`) installed in Unity Editor. See [Adding modules through the Unity Hub](https://docs.unity3d.com/hub/manual/AddModules.html).
2. You have to be logged into **coherence** **Cloud** via the coherence Hub window. See [Login through Unity](/2.3/getting-started/setup-a-project/test-in-the-cloud#login-through-unity) for more information.
   {% endhint %}

Press the **coherence Hub > Simulators > Build And Upload Simulator** butto&#x6E;*.*

<figure><img src="/files/WwU9bZYgOqeDdzoF9bfu" alt=""><figcaption></figcaption></figure>

When the build is finished, it will be uploaded to your currently selected organization and project in the Developer Portal.

## Connecting your Simulator to a Room or World

You can see your uploaded simulator builds on the Dashboard on the **Schemas & Builds** sections of your project.

{% hint style="warning" %}
Target frame rate on Simulator builds is forced at 30. This can be changed through the Runtime Settings asset in your Unity project. There's a setting to disable this behavior, or to change from 30 to a different target frame rate.
{% endhint %}

#### Reducing Simulator build size — EXPERIMENTAL ⚠️

<figure><img src="/files/VoFDE74qU2bpH0DuMz39" alt=""><figcaption></figcaption></figure>

Select the desired optimizations depending on your needs.

| Optimization            | What it does                                                                                                                                                                                                                                                        |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Strip Assets            | Project's textures and sound files are replaced with tiny and lightweight alternatives (dummies). Original assets are copied over to *\<project>/Library/coherence/AssetsBackup*. They are restored once the build process has finished.                            |
| Backup Assets           | The *Assets Backup* (found at *\<project>/Library/coherence/AssetsBackup*) is kept after the build process is completed, instead of deleted. This will take extra disk space depending on the size of the project, but is a safety convenience.                     |
| Compress Meshes         | Sets Mesh Compression on all your models to High.                                                                                                                                                                                                                   |
| Disable Static Batching | Static Batching tries to combine meshes at compile-time, potentially increasing build size. Depending on your project, static batching can affect build size drastically. Read more about [static batching](https://docs.unity3d.com/Manual/DrawCallBatching.html). |

{% hint style="info" %}
Once your Simulator is built and uploaded, you'll be prompted with the option to revert the settings to the ones you had applied before building. This is to avoid these settings from affecting other builds you make.
{% endhint %}


# Command-line arguments

{% hint style="info" %}
The following CLI flags can be specified on Unity Builds. They are read by the SDK via the [SimulatorUtility](https://unityapi.coherence.io/docs/v2.2.0/api/Coherence.SimulatorUtility.html) API.
{% endhint %}

| Flag                                     | Description                                                                                                                                             | SimulatorUtility                   |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| `--coherence-region <region>`            | `eu`, `us`, `usw`, `ap` or `local`.                                                                                                                     | `Region`                           |
| `--coherence-ip <ip>`                    | Specific IP to point to.                                                                                                                                | `Ip`                               |
| `--coherence-port <port>`                | Specific port to point to.                                                                                                                              | `Port`                             |
| `--coherence-room-id <room-id>`          | Specific Room to point to.                                                                                                                              | `RoomId`                           |
| `--coherence-room-tags <base64-tags>`    | A base64 enconded string containing the Room tags (space-separated). Example: `tag1 tag2 tag3`                                                          | `RoomTags`                         |
| `--coherence-room-kv-json <base64-json>` | <p>A base64 encoded string containing a JSON object literal with key-valure pairs. Example:</p><p><code>{"key1": "value1", "key2": "value2"}</code></p> | `RoomKV`                           |
| `--coherence-world-id <world-id>`        | Specific World ID to point to.                                                                                                                          | `WorldId`                          |
| `--coherence-simulation-server`          | Connect and behave as a Simulator.                                                                                                                      | `HasSimulatorCommandLineParameter` |
| `--coherence-simulator`                  | Same as `--coherence-simulation-server`.                                                                                                                | `HasSimulatorCommandLineParameter` |


# Advanced simulator authority

Some games require enhanced security against cheating or player griefing. This is done by giving authoritative privileges to [Simulators](/2.3/manual/simulation-server) only.

{% hint style="warning" %}
Advanced Simulator Authority is a specific feature set meant for advanced use cases. Most projects should consider simpler setups first, like [distributed authority](/2.3/manual/networking-state-changes/authority#distributed-client-authority) or simple [server-authoritative](/2.3/manual/networking-state-changes/authority/server-authoritative-setup). This approach adds complexity, especially around object creation and error handling.
{% endhint %}

### Configuring for cloud-hosted Replication Server

In the **Project Settings** section of the [Online Dashboard](/2.3/hosting/coherence-cloud/online-dashboard) under **Advanced Authority Config**, you can select which **Host Authority** features are enabled for Rooms and Worlds separately, under **Rooms Host Authority** and **Worlds Host Authority**.

### Configuring for local development

In the **coherence** [project settings](/2.3/manual/project-settings), under **Local Replication Server**, you can select which Host Authority features are enabled for a locally run Replication Server World. If you are manually launching the Replication Server from the CLI, the `--host-authority-features` parameter should be passed into the command with comma-separated dash-cased-enabled features names.

For example:

`replication-server worlds --host-authority-features=create-entities,validate-connection`

To select which Host Authority features are enabled for a locally run Room, you need to set `SelfHostedRoomCreationOptions.HostAuthority` at Room creation time.

{% hint style="warning" %}
If any host authority feature is enabled, the Replication Server will not allow Clients to be connected without a Simulator being connected as well.

If a Client tries to connect before a Simulator, the connection will be denied with the `ConnectionCloseReason.HostNotReady`.

If a Simulator disconnects, while other Clients are connected to the server, the Replication Server will forcefully disconnect all other Clients as well with the `ConnectionCloseReason.HostDisconnected`.
{% endhint %}

## Restricting Entity Creation

The `HostAuthority.CreateEntities` feature is used to only allow Simulators to create entities. Once created, these entities can have their state authority transferred and their lifetime managed by non-simulators, but no Client is allowed to create entities while this restriction is active.

{% hint style="warning" %}
By default, all CoherenceSyncs have [AuthorityTransferType](/2.3/manual/networking-state-changes/authority/authority-transfer#types-of-authority-transfer) set to "Steal". This means that malicious players could steal the authority of any entity and break the game.

Instead of manually changing the AuthorityTransferType on every new CoherenceSync, you can change the default value of it in the **coherence** [project settings](/2.3/manual/project-settings). See [Types of authority transfer](/2.3/manual/networking-state-changes/authority/authority-transfer#types-of-authority-transfer).
{% endhint %}

{% hint style="info" %}
With entity creation restriction enabled, the CoherenceSyncs that have the [Simulate In](/2.3/manual/components/coherence-sync#simulate-in) option set to *Client Side* or *Server Side With Client Input* and are spawned by a Client will automatically get destroyed. The ones set to *Server Side* will just get disabled.

Simulator can still use any of the available options. *Client Side* works the same as *Server Side* and has no effect on the Simulator-side entities, while the *Server Side With Client Input* should be used together with [CoherenceInput](/2.3/manual/components/coherenceinput).
{% endhint %}

### Disabling global query for Client connections on the Coherence Bridge

By default, when [Client connections](/2.3/manual/client-connections) are active, the [CoherenceBridge](/2.3/manual/components/coherence-bridge) will automatically create a global query entity on behalf of the Client. If the Client is not authorized to create entities, this results in an error on the Replication Server indicating that an entity creation was rejected. To avoid these error logs, the auto creation of the global query can be disabled in the CoherenceBridge configuration:

<figure><img src="/files/fDBNEYjynm9stJrERwr6" alt=""><figcaption><p>Uncheck the Create Global Query option</p></figcaption></figure>

[A global query can be created manually](/2.3/manual/simulation-server/advanced-simulator-authority/simulator-query-transfer) as part of a prefab by using the[ CoherenceGlobalQuery](/2.3/manual/components/coherenceglobalquery) component. This prefab can then be transferred to other clients from the simulator to give those clients access to the global client connections.

## Validating Client Connections

The `HostAuthority.ValidateConnection` feature is used to restrict who can connect to a World or a Room. Upon enabling this feature, the connected Simulator will receive a validation request on every connection attempt from a Client. The connection is allowed only if the Simulator responds with the accepted validation response.

To handle the connection validation requests, the Simulator can subscribe to `CoherenceBridge.onValidateConnectionRequest`. To respond to the validation request, call `Respond()` on the `ConnectionValidationRequest` provided, passing in the validation response:

```csharp
using Coherence.Brisk;
using Coherence.Toolkit;
using UnityEngine;

public class Example : MonoBehaviour
{
    public CoherenceBridge bridge;

    private void Awake()
    {
        bridge.onValidateConnectionRequest.AddListener(OnValidateConnectionRequest);
    }

    private void OnValidateConnectionRequest(ConnectionValidationRequest request)
    {
        // Your own validation logic goes here.
        var accept = true;

        // Call request.Respond() to accept or reject the connection.
        // This could be done later on (not on this frame), if needed.
        request.Respond(new ConnectionValidationResponse(accept));
    }
}
```

If the Simulator rejects the connection, the Client will receive a [connection denied error](/2.3/manual/components/coherence-bridge#onconnectionerror) with the `ConnectionCloseReason.ConnectionRejectedByHost`.

{% hint style="info" %}
The response can be handled asynchronously by storing the `request` and calling the `Respond()` at a later time.
{% endhint %}

{% hint style="info" %}
The validation is a subject to a **5-second timeout**. If a connection is not validated within that time period it will be automatically rejected, resulting in the Client receiving a "Connection denied" error with the`ConnectionCloseReason.ConnectionValidationTimeout` reason.
{% endhint %}

{% hint style="info" %}
In scenarios where multiple Simulators are connected to the Replication Server, the connection validation request is now sent to all connected Simulators. Only the first response received by the Replication Server is honored; subsequent responses from other Simulators are ignored.
{% endhint %}

### Custom user payload

Before initiating the connection, the user can set an optional custom user payload which will be sent to the Simulator for validation. The payload is of type `byte[]`, and can contain an **access token** or any other data. To send the payload for validation, you must set it **before** initiating the connection:

```csharp
bridge.SetConnectionValidationPayload(new CustomPayload(myToken));
bridge.JoinRoom(roomData); // or bridge.Connect(...);
```

### Custom host payload

When responding to a connection validation request, the Simulator can also send a custom payload back to the user. This is done by passing the payload to the `ConnectionValidationResponse` when calling the `Respond()` method.

{% hint style="warning" %}
The payload size is limited to 512 bytes.
{% endhint %}

The Client can access the payload sent by the Simulator depending if the connection validation was accepted or rejected:

* If the connection was accepted, the payload can be accessed by calling the [CoherenceBridge](/2.3/manual/components/coherence-bridge) function `GetValidatedHostPayload()` after the connection was established.
* Or, if the connection was rejected, the payload is contained inside the [connection denied error](/2.3/manual/components/coherence-bridge#onconnectionerror) together with the `ConnectionCloseReason.ConnectionRejectedByHost`.

```csharp
using Coherence.Brisk;
using Coherence.Common;
using Coherence.Connection;
using Coherence.Toolkit;
using UnityEngine;

[RequireComponent(typeof(CoherenceBridge))]
public class ConnectionValidationHandler : MonoBehaviour
{
    public string Password; // Set in the editor

    private void Start() {
        var bridge = GetComponent<CoherenceBridge>();
        bridge.onValidateConnectionRequest.AddListener(OnValidateConnectionRequest);

        bridge.onConnectionError.AddListener((_, exception) =>
        {
            if (exception is ConnectionDeniedException deniedException)
            {
                Debug.Log("Connection denied. " +
                          $"Reason: {deniedException.CloseReason}, " +
                          $"Message: {deniedException.HostPayload.AsString}");
            }
        });
    }

    private void OnValidateConnectionRequest(ConnectionValidationRequest request)
    {
        if (request.UserPayload.AsString == Password)
        {
            request.Respond(new ConnectionValidationResponse(true));
        }
        else
        {
            var message = new CustomPayload("Invalid password");
            request.Respond(new ConnectionValidationResponse(false, message));
        }
    }
}
```

## Kicking Client Connections

A Simulator can forcefully disconnect other Clients by kicking them. When kicking a Client, the Simulator can also send an optional host payload of type `byte[]` which will be sent to the kicked Client, together with the `ConnectionCloseReason.KickedByHost`.

```csharp
// On simulator
var payload = new CustomPayload("Kicked for griefing.");
bridge.KickConnection(clientID, payload);

// On client
bridge.onConnectionError.AddListener((bridge, exception) =>
{
    if (exception is ConnectionDeniedException deniedException &&
        deniedException.CloseReason == ConnectionCloseReason.KickedByHost)
    {
        var message = deniedException.HostPayload.AsString;
        Debug.Log($"Kicked with message: {message}");
    }
});
```

## Simulator payload

It is sometimes useful for the Client creating a room to pass information to the Simulator handling that room. If the information is public and can be seen by other Clients, using room Tags or a Key-Value dictionary is the best way to pass it.

If, however, the information is secret and should be known only to the Simulator, then we can use the **Simulator Payload**:

```csharp
// On the client
var roomCreationOptions = new RoomCreationOptions {
    SimPayload = roomPassword,
};

var roomsService = PlayerAccount.Main.Services.Rooms;
roomsService
    .GetRoomServiceForRegion("eu")
    .CreateRoom(OnRoomCreated, roomCreationOptions);

// On the simulator
string password = SimulatorUtility.Payload;
```

{% hint style="info" %}
This feature is also available for Worlds. The payload can be set via the [dashboard](/2.3/hosting/coherence-cloud/online-dashboard), in the **World configurator** (**Simulator configuration -> Optional simulator payload**).
{% endhint %}

## Known limitations

* The [Client Connections](/2.3/manual/client-connections) system is not fully operable when **Entity creation restriction** is enabled. While connections will be registered and their ClientIDs are available, the Client connection objects' state won't be synced and no commands can be sent for those objects. This applies only to the client-side connection objects. This limitation is slated to be removed in the future.


# Simulator query transfer

In an advanced Simulator setup, where entity creation is restricted to the Simulator, it is not possible for a Client to create their own queries. In [an unrestricted setup](/2.3/manual/networking-state-changes/authority/server-authoritative-setup#interaction-with-livequeries) you can create a live query Prefab that has a [CoherenceSync ](/2.3/manual/components/coherence-sync)behaviour with the *Simulate On* property set to *Server Side with Client Input*. However, in order to provide a Client with a live query in an entity-restricted setup, the Simulator has to create the live query on behalf of the Clients and transfer the input authority back.

<pre class="language-csharp"><code class="lang-csharp"><strong>using UnityEngine;
</strong>using System.Collections.Generic;
using Coherence.Connection;
using Coherence.Toolkit;

public class SimulatorConnectionHandler : MonoBehaviour
{
    public CoherenceBridge bridge;
    public CoherenceSync liveQueryPrefab;

    private Dictionary&#x3C;ClientID, CoherenceSync> clientQueries = new();

    public void Start()
    {
        bridge.ClientConnections.OnCreated += HandleClientCreated;
        bridge.ClientConnections.OnDestroyed += HandleClientDestroyed;
    }

    public void OnDestroy()
    {
        bridge.ClientConnections.OnCreated -= HandleClientCreated;
        bridge.ClientConnections.OnDestroyed -= HandleClientDestroyed;
    }

    private void HandleClientCreated(CoherenceClientConnection client)
    {
        if (client.IsMyConnection)
        {
            // This example is only creating live queries for other clients.
            return;
        }

        // Create a live query for the client and transfer the input authority so
        // they get the benefit of the query, but are not allowed to modify it 
        // directly.
        var clientQuery = Instantiate(liveQueryPrefab);
        clientQuery.TransferAuthority(client.ClientId, Coherence.AuthorityType.Input);

        clientQueries.Add(client.ClientId, clientQuery);
    }

    private void HandleClientDestroyed(CoherenceClientConnection client)
    {
        if (client.IsMyConnection)
        {
            return;
        }

        // Destroy the query that belonged to the disconnected client.
        var clientQuery = clientQueries[client.ClientId];
        Destroy(clientQuery.gameObject);

        clientQueries.Remove(client.ClientId);
    }
}
</code></pre>

Constructing a Prefab that has Simulator authority but benefits a Client with the area of interest is simple. It requires that the *Authority Transfer* mode is *Request* and that there is a [Coherence Live Query](/2.3/manual/components/coherence-live-query) component. It is also possible to add any kind of query to these Prefabs or multiple types and the Client will benefit from them all.

<figure><img src="/files/2GoNasjY54H34gXaMBdW" alt=""><figcaption><p>The <strong>Simulate in</strong> field is set to <em>Client Side</em>.</p></figcaption></figure>

{% hint style="warning" %}
Note that the **Simulate In** field is set to *Client Side*. This is appropriate for this setup even though the state authority of this entity is a Simulator, since from the point of view of the Replication Server all Simulators are Clients as well.
{% endhint %}


# Advanced topics


# Single-player gameplay

How coherence behaves when a Client is not connected

Even though **coherence** is a networking solution, there might be instances when a Scene configured for online play is used offline, without connecting to a Replication Server. This can be useful for creating gameplay that works in an offline game mode (like a tutorial), or simply a game that can **connect and disconnect seamlessly** during uninterrupted gameplay.

The ability to create Prefabs and code that can be **used** **both online and offline** is an great tool that in the long term can streamline the development process, avoid duplicated code, ultimately creating less bugs.

## Dos and Don'ts

To ensure that the code you write doesn't break when offline, follow these recommendations:

* Check if a `CoherenceBridge` is connected using `CoherenceBridge.isConnected`.
* `CoherenceSync` components also have a reference to the associated bridge, so if one is present in the Scene you can use `sync.CoherenceBridge.isConnected` for convenience.
* When offline, `CoherenceSync.EntityState` is `null`. Use this to your advantage to identify the state of the connection.
* Authority is assumed on offline entities (`CoherenceSync.HasStateAuthority` always returns `true`).
* You can use [commands](/2.3/manual/networking-state-changes/commands). They will be routed to local method calls.
* When offline, some events on **coherence** components (e.g., `CoherenceBridge.OnLiveQuerySynced`) won't be fired, so review any game logic that depends on them.
* [Persistence](broken://pages/-MYgPvUyuL6aH8ZrwmnB) and [uniqueness](broken://pages/-MYgPvUyuL6aH8ZrwmnB#uniqueness-and-uuid) are not resolved when offline, so don't make assumptions about their network state.
* When offline, if you have a Prefab in the Scene that is set to *Simulate In Server Side*, it won't be automatically removed (since there's no connection, hence **coherence** can't infer if it's a Simulator or a Client connection). You can use `SimulatorUtility.IsSimulator` in an `OnEnable()` and deactivate it.
* In case of a server-authoritative scenario using `CoherenceInput`, you might want to isolate state-changing code that would run in the Simulator into its own script. This way, it can be reused to directly affect the state of the entity when the game is offline.

See below for a more in-depth description of how the different components behave.

## Components behavior when offline

This section describes how the different components offered by **coherence** behave when the game is offline.

### CoherenceBridge

Because the `CoherenceBridge` never tries to connect, it won't fire any connection-related events.

You won't be able to query the list of [ClientConnections](/2.3/manual/client-connections), and all Room or World related data or [Services](/2.3/hosting/coherence-cloud/game-services) data won't be there.

However, you will be able to access through the `CoherenceBridge` what is part of the setup at edit time. For instance, you will be able to inspect the list of `CoherenceSyncConfig` objects in order to [instantiate connected Prefabs](/2.3/manual/networking-state-changes/asset-management/using-coherencesyncconfig-to-instantiate-gameobjects).

### CoherenceSync

Connected Prefabs that feature a `CoherenceSync` can be instantiate and destroyed like usual while offline.

<figure><img src="/files/20sG39cLbDqC5Ts4DW0s" alt=""><figcaption><p>The Inspector of a non-connected CoherenceSync</p></figcaption></figure>

#### Authority

Because it's always the local Client that creates instances of connected Prefabs, it will automatically receive **full authority**, [both state and input](/2.3/manual/networking-state-changes/authority#authority-types), on all of them. Consequently, the `OnStateAuthority` callback will be invoked when the object is instantiated, in `OnEnable()`. Check on `sync.HasStateAuthority` will return true, as early as `Awake()`.

The Client has authority to **manipulate its state**, and can destroy the Prefab instance at will.

If a Component has been configured to be enabled/disabled as a result of authority changes (that is, using [Component Actions](https://docs.coherence.io/2.3/manual/advanced-topics/pages/-MYMcuWV2fBpQVo-zzDr#id-5.-disable-input-on-replicated-object)), it will be enabled.

#### Network Commands

No change in behavior. [Network Commands](/2.3/manual/networking-state-changes/commands) will invoke the corresponding method with a direct invocation, with no network delay incurred.

#### Persistent entities

Prefabs marked as [Persistent](broken://pages/-MYgPvUyuL6aH8ZrwmnB) will not persist after an offline game session. They will be destroyed when the Scene they belong to is unloaded, and will not be automatically recreated if the Scene is re-loaded.

Persistence is tied to the World or Room the Client is connected to. If you need objects to persist between different offline sessions, you need to store their state some other way.

#### Unique entities

Like persistence, [uniqueness](broken://pages/-MYgPvUyuL6aH8ZrwmnB#uniqueness-and-uuid) is also verified within the context of the Room or World the Client is connected to, and is generally used for ensuring that a different Client can't bring an already existing entity to the simulation.

When offline, no check happens for uniqueness, meaning that unique entities can be instantiated multiple times. It is therefore up to the local gameplay code to make sure this doesn't happen in the first place.

#### Simulate in Server-side

Any Prefab for which the property *Simulate In* has been set to *Server-Side* will not be automatically deactivated on instantiation.

To ensure such a Prefab doesn't appear in an offline session, make sure to deactivate it in its code by using:

```csharp
if (!SimulatorUtility.IsSimulator)
{
    gameObject.SetActive(false);
}
```

### LiveQuery

`LiveQuery` components will not have any effect offline. However, keep in mind that they will try to find the `CoherenceBridge`, so if none is present they will throw an error. For this reason it's a good idea to keep them together, and only have a `LiveQuery` in the scene if a `CoherenceBridge` is present.

### CoherenceNode

Any `CoherenceNode` component will have no effect. There are no drawbacks for leaving it inside the Prefabs.

### CoherenceInput

Given that it's inherently meant to be used in a Client-Server scenario, `CoherenceInput` has no meaning offline.

However, you can safely leave the component on your Prefabs, and architect your scripts so that rather than sending inputs to `CoherenceInput` regardless, they first check if the Client is connected and, in case of a negative answer, manipulate the entity's state instead.

It can be a good idea to isolate the code used to manipulate the entity's state during **prediction**, and reuse it for offline behavior.

* If the game is online, input is sent to the Simulator via `CoherenceInput`, while at the same time prediction is done locally and applied. On the Simulator, the same code used from the Client to do prediction is used to compute the final state. Once an update is received, reconciliation code kicks in and corrects any mismatches.
* In offline mode, the same code used for the prediction is used for driving the entity's state instead, and no input is forwarded to `CoherenceInput`.


# Code stripping

Unity supports [code stripping](https://docs.unity3d.com/Manual/ManagedCodeStripping.html) as part of the engine. Code stripping automatically removes unused or unreachable code during the Unity build process, to decrease the application’s final size.

{% hint style="danger" %}
Setting code stripping above Minimal level is risky and might break your game by removing code that's needed for it to run.
{% endhint %}

Starting from 1.4.0, we're generating a `link.xml` file in `Assets/coherence/link.xml` with the needed directives to support the coherence SDK. This file is generated at build time, and deleted after the build.

If you're on previous versions of the SDK, and you're considering using code stripping above Low level, add the following link.xml file anywhere in your project (e.g., `Assets/link.xml`):

```xml
<linker>
  <assembly fullname="System">
    <type fullname="System.Net.Configuration.ConnectionManagementSection" />
    <type fullname="System.Net.Configuration.ConnectionManagementElementCollection" />
    <type fullname="System.Net.Configuration.NetSectionGroup" />
  </assembly>

  <assembly fullname="System.Configuration">
    <type fullname="System.Configuration.ExeConfigurationHost" />
  </assembly>
</linker>
```

Read more on how link.xml works in Unity on their [code stripping](https://docs.unity3d.com/Manual/ManagedCodeStripping.html) section.

In any case, there's no one-size-fits-all solution to be safe when it comes to code stripping. It highly depends on your project, and also your dependencies (third party libraries and assets used).

If you are experiencing issues with coherence while using code stripping,[ reach out to us](https://community.coherence.io/).


# Team workflows




---

[Next Page](/llms-full.txt/1)

