# Unity NGO

Изучите, как размещать проекты Unity на Edgegap, используя методы из [Пример комнаты босса NGO](https://unity.com/demos/small-scale-coop-sample).

{% hint style="info" %}
Этот образец **не требует никаких Unity Gaming Services (UGS)**, Multiplay или Relays для запуска.
{% endhint %}

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

## ✔️ Подготовка

Прежде чем начать, вам потребуется:

* Unity 6 - [скачать с помощью Unity Hub](https://unity.com/releases/unity-6),
* Проект Unity NGO \[Netcode for Game Objects] Boss Room Sample (модифицирован для Edgegap):
  * [скачать с Github](https://github.com/edgegap/netcode-sample-unity-ngo-bossroom).

## ⚡ Развертывание и подключение

### 1. Разверните сервер на Edgegap

☑️ Чтобы начать, вам нужно [создать бесплатную учетную запись на Edgegap](https://app.edgegap.com/auth/register). Кредитная карта не требуется.

☑️ [Создайте новую версию приложения для вашего приложения](https://app.edgegap.com/application-management/applications/unity-ngo-bossroom-sample/versions/create), выберите NGO Boss Room Sample.

☑️ [Разверните сервер с вашей версией приложения NGO Boss Room Sample](https://app.edgegap.com/deployment-management/deployments/list).

☑️ [Откройте сведения о новом развертывании](https://app.edgegap.com/deployment-management/deployments/list) и найдите ваши уникальные одноразовые данные для подключения:

* **Внешний порт** в формате `30854`  (5 цифр).

☑️ Перейдите на вкладку Логи и найдите (CTRL+F) ваши уникальные одноразовые данные для подключения:

* `ARBITRIUM_PUBLIC_IP` в формате `172.234.244.38` .

✅ Теперь вы можете перейти к следующему шагу.

### 2. Подключение из редактора

☑️ Откройте ваш новый проект в Unity.

☑️ Убедитесь, что вы открыли сцену: `Assets/Scenes/MainMenu.unity`.

☑️ Нажмите кнопку ▶️ Play, чтобы запустить клиент игры:

* нажмите **START WITH DIRECT IP** кнопку,
* выберите вкладку **JOIN WITH IP.**

☑️ Введите данные для подключения из предыдущего шага.

☑️ Нажмите **JOIN** кнопку, чтобы подключиться к вашему серверу.

☑️ Подключите второго виртуального игрока с помощью [Multiplayer Play Mode](https://docs-multiplayer.unity3d.com/mppm/current/about/) или [ParrelSync](https://github.com/VeriorPies/ParrelSync).

🙌 Поздравляем с вашим первым развертыванием на Edgegap!

## ✏️ Настроить сборку сервера

{% hint style="success" %}
См. [Unity](/ru/unity.md) для Unity, чтобы **узнать, как собирать и настраивать серверы**.
{% endhint %}

### Запуск в режиме выделенного сервера

Для запуска этого примера в режиме выделенного сервера мы внесли следующие изменения:

{% tabs %}
{% tab title="Инициализация сервера" %}
Новый скрипт (добавлен в вашу `MainMenu` сцену в новый пустой `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 вызывается перед первым обновлением кадра
        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($"Не удалось найти сопоставление порта, убедитесь, что имя порта вашей версии приложения совпадает с \"{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="Управление подключениями" %}
Изменённые файлы:

<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); // Требуется также установить полезную нагрузку подключения для хоста, так как хост тоже является клиентом</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                // StartHost NGO запускает всё
<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="Совместимость с редактором/сервером" %}
Изменить файлы:

<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]: имя порта по умолчанию на Edgegap

[^2]: имя игрока для сервера может быть любым значением

[^3]: только p2p ⇒ закомментировать это

[^4]: запуск вместо этого как выделенный сервер

[^5]: Совместимость с редактором ⇒ закомментировать это


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.edgegap.com/ru/docs/sample-projects/unity-netcodes/unity-netcode-on-edgegap.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
