# Unity NGO

Explore how to host Unity projects on Edgegap using techniques from the [NGO Boss Room Sample](https://unity.com/demos/small-scale-coop-sample).

{% hint style="info" %}
This sample **does not require any Unity Gaming Services (UGS)**, Multiplay, or Relays to run.
{% endhint %}

{% embed url="<https://youtu.be/8Qi-wXswjkw>" %}

## ✔️ Preparation

Before we start, you will need:

* Unity 6 - [download using Unity Hub](https://unity.com/releases/unity-6),
* Unity NGO \[Netcode for Game Objects] Boss Room Sample project (modified for Edgegap):
  * [download from Github](https://github.com/edgegap/netcode-sample-unity-ngo-bossroom).

## ⚡ Deploy and Connect

### 1. Deploy a Server on Edgegap

☑️ To get started, you'll need to [create a free account with Edgegap](https://app.edgegap.com/auth/register). No credit card required.

☑️ [Create a new app version for your application](https://app.edgegap.com/application-management/applications/unity-ngo-bossroom-sample/versions/create), choose NGO Boss Room Sample.

☑️ [Deploy a server with your NGO Boss Room Sample app version](https://app.edgegap.com/deployment-management/deployments/list).

☑️ [Open your new deployment's details](https://app.edgegap.com/deployment-management/deployments/list) and find your unique, one-time connection details:

* **External Port** in format `30854`  (5 digits).

☑️ Navigate to tab Logs and find (CTRL+F) your unique, one-time connection details:

* `ARBITRIUM_PUBLIC_IP` in format `172.234.244.38` .

✅ You may now proceed to the next step.

### 2. Connect from Editor

☑️ Open your new project in Unity.

☑️ Verify that you have opened scene: `Assets/Scenes/MainMenu.unity`.

☑️ Press the ▶️ Play button to start your game client:

* press **START WITH DIRECT IP** button,
* select tab **JOIN WITH IP.**

☑️ Input connection details from previous step.

☑️ Press **JOIN** button to connect to your server.

☑️ Connect a second virtual Player with [Multiplayer Play Mode](https://docs-multiplayer.unity3d.com/mppm/current/about/) or [ParrelSync](https://github.com/VeriorPies/ParrelSync).

🙌 Congratulations on your first Deployment on Edgegap!

## ✏️ Customize Server Build

{% hint style="success" %}
See [unity](https://docs.edgegap.com/unity "mention") for Unity to **learn how to build and customize servers**.
{% endhint %}

### Run as Dedicated Server

For this sample to run as dedicated server, we made the following changes:

{% tabs %}
{% tab title="Server Initialization" %}
New script (added to your `MainMenu` scene in a new empty `GameObject`):

<pre class="language-csharp" data-title="Assets/Scripts/EdgegapServerStarter.cs" data-line-numbers><code class="lang-csharp">using System;
using System.Collections;
using System.Collections.Generic;
using Unity.BossRoom.ConnectionManagement;
using UnityEngine;

namespace Unity.Multiplayer.Samples.BossRoom
{
    public class EdgegapServerStarter : MonoBehaviour
    {
<strong>        public string portMapName = <a data-footnote-ref href="#user-content-fn-1">"gameport"</a>;
</strong>
        // Start is called before the first frame update
        void Start()
        {
            if (Application.isBatchMode)
            {
                ConnectionManager connectionManager = GameObject.Find("ConnectionManager").GetComponent&#x3C;ConnectionManager>();
<strong>                string internalPortAsStr = Environment.GetEnvironmentVariable($"ARBITRIUM_PORT_{portMapName.ToUpper()}_INTERNAL");
</strong>
                if (internalPortAsStr == null || !ushort.TryParse(internalPortAsStr, out ushort port))
                {
                    throw new Exception($"Could not find port mapping, make sure your app version port name matches with \"{portMapName}\"");
                }

<strong>                connectionManager.StartHostIp("<a data-footnote-ref href="#user-content-fn-2">SERVER</a>", "0.0.0.0", port);
</strong>            }
        }
    }
}
</code></pre>

{% endtab %}

{% tab title="Connection Management" %}
Modified files:

<pre class="language-csharp" data-title="Assets/Scripts/ConnectionManagement/ConnectionMethod.cs"><code class="lang-csharp"><strong>116        public override async Task SetupHostConnectionAsync()
</strong>117        {
<strong>118            <a data-footnote-ref href="#user-content-fn-3">//SetConnectionPayload(GetPlayerId(), m_PlayerName); // Need to set connection payload for host as well, as host is a client too</a>
</strong>119            var utp = (UnityTransport)m_ConnectionManager.NetworkManager.NetworkConfig.NetworkTransport;
120            utp.SetConnectionData(m_Ipaddress, m_Port);
121        }
</code></pre>

<pre class="language-csharp" data-title="Assets/Scripts/ConnectionManagement/ConnectionState/StartingHostState.cs"><code class="lang-csharp"><strong>66        async void StartHost()
</strong>67        {
              ...

72                // NGO's StartHost launches everything
<strong>--                <a data-footnote-ref href="#user-content-fn-3">//if (!m_ConnectionManager.NetworkManager.StartHost())</a>
</strong><strong>73                <a data-footnote-ref href="#user-content-fn-4">if (!m_ConnectionManager.NetworkManager.StartServer())</a>
</strong>74                {
75                    StartHostFailed();
76                }

              ...
</code></pre>

<pre class="language-csharp" data-title="Assets/Scripts/Gameplay/GameplayObjects/Character/ClientCharacter.cs"><code class="lang-csharp"><strong>112        public override void OnNetworkSpawn()
</strong>113        {
               ...

125            m_ServerCharacter.IsStealthy.OnValueChanged += OnStealthyChanged;
126            m_ServerCharacter.MovementStatus.OnValueChanged += OnMovementStatusChanged;
<strong>127            <a data-footnote-ref href="#user-content-fn-3">//OnMovementStatusChanged(MovementStatus.Normal, m_ServerCharacter.MovementStatus.Value);</a>
</strong> 
               ...
</code></pre>

{% endtab %}

{% tab title="Editor/Server Compatibility" %}
Modify files:

<pre class="language-csharp" data-title="Assets/Scripts/ConnectionManagement/ConnectionState/HostingState.cs"><code class="lang-csharp"><strong>148        ConnectStatus GetConnectStatus(ConnectionPayload connectionPayload)
</strong>149        {
               ...
                
<strong>155            <a data-footnote-ref href="#user-content-fn-5">//if (connectionPayload.isDebug != Debug.isDebugBuild)</a>
</strong><strong>156            //{
</strong><strong>157            //    return ConnectStatus.IncompatibleBuildType;
</strong><strong>158            //}
</strong>
               ...
</code></pre>

{% endtab %}
{% endtabs %}

[^1]: default port name on Edgegap

[^2]: player name for server can be any value

[^3]: p2p only ⇒ comment this out

[^4]: start as dedicated server instead

[^5]: Editor compatibility ⇒ comment this out
