# Unity NGO

Edgegap에서 Unity 프로젝트를 호스팅하는 방법을 다음에서 사용된 기법을 통해 알아보세요 [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] 보스룸 샘플 프로젝트(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 보스룸 샘플을 선택하세요.

☑️ [NGO 보스룸 샘플 앱 버전으로 서버를 배포하세요](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`.

☑️ ▶️ 재생 버튼을 눌러 게임 클라이언트를 시작하세요:

* 누르기 **직접 IP로 시작** 버튼,
* 탭 선택 **IP로 참가.**

☑️ 이전 단계의 연결 정보를 입력하세요.

☑️ 버튼을 누르세요 **참가** 서버에 연결하려면 버튼을 누르세요.

☑️ 두 번째 가상 플레이어를 연결하려면 [멀티플레이어 플레이 모드](https://docs-multiplayer.unity3d.com/mppm/current/about/) 또는 [ParrelSync](https://github.com/VeriorPies/ParrelSync).

🙌 Edgegap에서의 첫 배포를 축하합니다!

## ✏️ 서버 빌드 사용자화

{% hint style="success" %}
참고 [unity](https://docs.edgegap.com/docs.edgegap.com-ko/unity "mention") 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.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
        // 초기화에 사용
        {
            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">서버</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                // NGO의 StartHost는 모든 것을 실행합니다
<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]: 에디터 호환성 ⇒ 이 부분을 주석 처리
