# Prefab setup

In this section, we will learn how to prepare a prefab for network replication.

### **1.** Create a prefab and move it to Resources

Add an asset and create a *prefab* of it. Make sure the *prefab* is in a `Resources` folder in your Unity project.

Here is an example:

#### 1.1 Create a simple Cube in the scene

`GameObject -> 3D Object -> Cube`

#### 1.2 Convert the Cube into a prefab

Create a `Resources` folder in your Project. Drag the Cube into the Resources folder to turn it into a prefab.

<div align="left"><img src="https://3643360286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWd0ZPEK7vE9nkE0b7G%2F-MYvG7OmGmB6UohO3RKl%2F-MYvGuyw-FsLi5Ll-agA%2Fimage.png?alt=media&#x26;token=44210db2-d52c-47e7-b207-d5e6572c945f" alt=""></div>

{% hint style="warning" %}
It's important that your **prefab** is in a ***Resources folder*** so that Unity can load it at runtime. This is a Unity requirement, more info [here](https://docs.unity3d.com/ScriptReference/Resources.Load.html).&#x20;
{% endhint %}

### **2. Add CoherenceSync to the prefab**

<div align="left"><img src="https://3643360286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWd0ZPEK7vE9nkE0b7G%2F-MYvH0TdGWulxyKR7uoV%2F-MYvHBtXezxfAnxoE_86%2Fimage.png?alt=media&#x26;token=5d7cb9b4-bbd1-423c-a5bb-c159c697f29d" alt=""></div>

The `CoherenceSync` component will help you prepare an object for network synchronization during design time. It also exposes an API that allows us to manipulate the object during runtime.

`CoherenceSync` will query 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 such as `PlayerInput` and even scripts that came with *Asset Store* packages you may have downloaded. &#x20;

### 3. Select variables to replicate

Select which variables you would like to sync across the network. Initially, this will probably be the `Transform` settings; **position**, **rotation**, **scale**.

Under `Synchronization`, click `Select fields and methods`.

![](https://3643360286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWd0ZPEK7vE9nkE0b7G%2F-Ma3wvuvMY7zHD0EN-IT%2F-Ma4MdZs_HS56X5bb-E8%2FcoherenceSync2.png?alt=media\&token=22cce2c0-21aa-47cc-9190-8359fa7caa90)

In the *Bindings* dialog, select *position, rotation and scale.*

![](https://3643360286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWd0ZPEK7vE9nkE0b7G%2F-Ma3wvuvMY7zHD0EN-IT%2F-Ma4MtEtiZgP2jZ6RV77%2Fbindings2.png?alt=media\&token=1f0e64b2-c7a3-4fa1-a062-fd089981d3a9)

Close the *Bindings* dialo&#x67;*.*

### **4. Add an input script**

This simple input script will use WASD or the Arrow keys to move the prefab around the scene.&#x20;

Click on `Assets -> Create -> C# Script`.

Name it `Move.cs`. Copy-paste the following content into the file.

{% code title="Move.cs" %}

```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Move : MonoBehaviour
{
    public float speed = 1f;

    void Update()
    {
        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");
    
        var spf = speed * Time.deltaTime;

        transform.position += transform.forward * (v * spf);
        transform.position += transform.right * (h * spf);
    }
}

```

{% endcode %}

Wait for Unity to compile the file, then add it onto the prefab.

![](https://3643360286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWd0ZPEK7vE9nkE0b7G%2F-Ma3wvuvMY7zHD0EN-IT%2F-Ma4NOn19K6XfkcuLdIX%2FmoveScript.png?alt=media\&token=bdd13d5e-a3a8-465c-8591-707ffa2f056f)

### 5. Disable Input on replicated object

We have added a `Move` script to the prefab. This means that if we just run the scene, we will be able to use the keyboard to move the object around.

But what happens on another client where this object is not authoritative, but rather replicated? We will want the position to be replicated over the network, without the keyboard input interfering with it.

Open the `Events` section in `CoherenceSync`. Add a new `On Network Instantiation` handler by clicking on the **plus sign** next to it.

![](https://3643360286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWd0ZPEK7vE9nkE0b7G%2F-Ma3wvuvMY7zHD0EN-IT%2F-Ma4NjE0GRxKlwGSThNr%2Fevent.png?alt=media\&token=44b1b6cf-a338-476b-9627-d9fcb76c78d9)

Pull the Cube prefab into the **Runtime Only / None (Object)** field.

Now click the dropdown **No Function** and select `Move -> bool enabled`.

<div align="left"><img src="https://3643360286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWd0ZPEK7vE9nkE0b7G%2F-MYvKC8nR2eFSsYq3lGX%2F-MYvKn-mgPnDM_1OshSk%2Fimage.png?alt=media&#x26;token=896295c8-0f6c-43c4-afed-927d148a5123" alt=""></div>

Leave the Boolean field unchecked.

<div align="left"><img src="https://3643360286-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MWd0ZPEK7vE9nkE0b7G%2F-MYvKC8nR2eFSsYq3lGX%2F-MYvL3GS429HvWIe6KIs%2Fimage.png?alt=media&#x26;token=b08b5c69-c2d3-4f39-9500-2de02126a5cf" alt=""></div>

### &#x36;**. Additional CoherenceSync settings**

From the `CoherenceSync` component you can configure settings for **Lifetime** (`Session-based` or `Persistent`, **Authority transfer** (`Request` or `Steal`), **Authority model** (`Client Side` or `Server Side with Client Input`) and **Adoption** settings for when local persistent entities are orphaned.&#x20;

You can find more information in the [SDK Fundamentals](https://docs.coherence.io/0.4.14/get-started/broken-reference). \
\
There are also some **Events** that are triggered at different times.&#x20;

* `On Networked Instantiation` (when the GameObject is instantiated)
* `On Networked Destruction` (when the GameObject  is destroyed)
* `On Before Authority Transfer` (before authority over the GameObject is transferred from one client/simulator to another)
* `On After Authority Transfer` (after the GameObject's Authority has been transferred to another client/simulator).

## Extras

Some extra scripts that are part of the Network Playground that may be useful.

{% tabs %}
{% tab title="Coherence Handler" %}

```
An Event System you put on the Prefab with coherenceSync
that can handle Network Events and Commands
```

{% endtab %}

{% tab title="C#" %}

```csharp
using UnityEngine;
using UnityEngine.Events;
using Coherence.Toolkit;

public class CoherenceHandler : MonoBehaviour
{
    private CoherenceSync sync;

    public UnityEvent onAuthorityGained;
    public UnityEvent onAuthorityLost;
    public UnityEvent onCommandReceived;
    public UnityEvent onEventReceived;

    private GameObject fxInstance;

    private void Awake()
    {
        sync = GetComponent<CoherenceSync>();
    }

    public void Adopt()
    {
        if (!sync || sync.isSimulated)
        {
            return;
        }

        sync.RequestAuthority();
    }

    public void Command(CoherenceSync sender)
    {
        sync.SendCommand(sender, "CoherenceHandler.ReceiveCommand");

        ReceiveCommand(); // reproduce locally
    }

    public void SendEvent()
    {
        foreach (var s in CoherenceSync.instances.Values)
        {
            if (!s || s == sync)
            {
                continue;
            }

            s.SendCommand(sync, "CoherenceHandler.ReceiveEvent");
            s.SendMessage("ReceiveEvent", SendMessageOptions.DontRequireReceiver); // reproduce locally
        }
    }

    public void ReceiveCommand()
    {
        onCommandReceived.Invoke();
    }

    public void ReceiveEvent()
    {
        onEventReceived.Invoke();
    }

    public void OnAuthorityTransfer(bool gained)
    {
        if (gained)
        {
            onAuthorityGained.Invoke();
        }
        else
        {
            onAuthorityLost.Invoke();
        }
    }

    public void InstantiateFX(GameObject fx)
    {
        if (fxInstance)
        {
            Destroy(fxInstance);
        }

        var t = fx.transform;
        fxInstance = Instantiate(fx, transform.position + t.position, transform.rotation);
    }
}

```

{% endtab %}

{% tab title="" %}

```
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Coherence Connection Events" %}

```
An Event System you can put on an empty game object in your 
scene that handles Global Connection/Disconnection
```

{% endtab %}

{% tab title="C#" %}

```csharp
using UnityEngine;
using UnityEngine.Events;
using Coherence;

public class CoherenceConnectionEvents : MonoBehaviour
{
    public UnityEvent onConnect;
    public UnityEvent onDisconnect;

    private void OnEnable()
    {
        Coherence.Network.OnConnected += OnConnect;
        Coherence.Network.OnDisconnected += OnDisconnect;
    }

    private void OnDisable()
    {
        Coherence.Network.OnConnected -= OnConnect;
        Coherence.Network.OnDisconnected -= OnDisconnect;
    }

    private void OnConnect()
    {
        onConnect.Invoke();
    }

    private void OnDisconnect()
    {
        onDisconnect.Invoke();
    }
}

```

{% endtab %}
{% endtabs %}
