# Photon Bolt

Это руководство поможет вам создать безголовый сервер на Edgegap для проекта Unity, используя Photon Bolt в качестве сетевого решения.

В этом руководстве мы будем использовать пользовательский демонстрационный проект в качестве примера.

### Подготовка проекта Unity

### Клонирование проекта Unity

Первый шаг — клонировать демонстрационный игровой проект Edgegap из git. Вы можете сделать это с помощью этой команды в командной строке:

Команда создаст папку, содержащую исходный проект Unity, под названием `demo-game`.

После завершения процесса вы можете открыть Unity Hub и добавить проект, нажав `Add` кнопку на вкладке Projects, а затем найти папку проекта на вашем компьютере:

Чтобы открыть проект, вам понадобится корректная версия Unity. В нашем случае мы используем Unity `2020.3.3`. Вы можете найти её в архиве загрузок Unity: <https://unity3d.com/get-unity/download/archive>.

После завершения установки вы можете выбрать новую версию Unity через выпадающее меню рядом с названием проекта в Unity Hub:

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

### Настройка игры

### Настройка Photon Bolt

#### Добавьте Photon App ID и скомпилируйте Bolt

Чтобы игра могла взаимодействовать со службами Photon, необходимо добавить приложение в вашу панель управления Photon. Если у вас ещё нет аккаунта Photon, его можно легко создать на их [веб-сайте](https://id.photonengine.com/Account/).

После входа вы можете создать приложение и дать ему имя. У каждого приложения есть уникальный `App ID`. Вам нужно скопировать и вставить этот ID в окно `Bolt Settings` внутри проекта Unity:

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-85755915f46bb51ed45784518d86ce278e998650%2Funity_photon_bolt_settings.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-fccf1cdf65056d42522cd4405f5a5dfbc5265106%2Funity_photon_bolt_app_id.png?alt=media" alt=""><figcaption></figcaption></figure>

После ввода ID можно закрыть окно Bolt Settings. В том же меню `Bolt` как и раньше, вам нужно выполнить два действия: `Update Prefab Database` и `Compile Assembly`соответственно.

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-93c9dc4b160db8a4b12142313da2c48bdb6a05cb%2Funity_photon_bolt_compile.png?alt=media" alt=""><figcaption></figcaption></figure>

На этом этапе вы должны иметь возможность запустить `StartScene` сцену игры без ошибок или предупреждений в отладочной консоли. Однако начать игру на сервере пока что нельзя.

На этом завершаются общие изменения, необходимые для работы вашего Photon Bolt. Эти изменения подойдут как для клиентов, так и для серверов вашей игры.

### Подготовка безголового сервера

Чтобы ваше приложение эффективно работало с контейнерами, нужно внести несколько изменений в игру для создания сборки «безголового сервера». Для большинства проектов это потребует лишь нескольких простых шагов.

#### Требования к проекту Unity

Прежде всего, важно отметить, что режим безголового сервера Photon Bolt требует загрузки сцены, содержащей скрипт под названием `HeadlessServerManager`.

Базовый, неизменённый скрипт (взятый из документации Bolt) выглядит так:

```cs
using System;
using Bolt.Matchmaking;
using Bolt.Photon;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Bolt.Samples.HeadlessServer
{
    public class HeadlessServerManager : Bolt.GlobalEventListener
    {
        public string Map = "";
        public string GameType = "";
        public string RoomID = "";

        public override void BoltStartBegin(" alt=""><figcaption></figcaption></figure>
        {
            // Зарегистрируйте любые используемые Protocol Token
            BoltNetwork.RegisterTokenClass<PhotonRoomProperties>();
        }

        public override void BoltStartDone()
        {
            if (BoltNetwork.IsServer)
            {
                // Создайте некоторые настраиваемые свойства комнаты
                PhotonRoomProperties roomProperties = new PhotonRoomProperties();

                roomProperties.AddRoomProperty("t", GameType); // например: тип игры
                roomProperties.AddRoomProperty("m", Map); // например: id карты

                roomProperties.IsOpen = true;
                roomProperties.IsVisible = true;

                // Если RoomID не был задан, создайте случайный
                if (RoomID.Length == 0)
                {
                    RoomID = Guid.NewGuid().ToString();
                }

                // Создайте комнату Photon
                BoltMatchmaking.CreateSession(
                    sessionID: RoomID,
                    token: roomProperties,
                    sceneToLoad: Map
                );
            }
        }

        // Используется для инициализации
        void Start()
        {
            // Получите пользовательские аргументы из командной строки
            Map = GetArg("-m", "-map") ?? Map;
            GameType = GetArg("-t", "-gameType") ?? GameType; // напр.: получить тип игры из командной строки
            RoomID = GetArg("-r", "-room") ?? RoomID;

            // Проверьте запрошенный уровень
            var validMap = false;

            foreach (string value in BoltScenes.AllScenes)
            {
                if (SceneManager.GetActiveScene().name != value)
                {
                    if (Map == value)
                    {
                        validMap = true;
                        break;
                    }
                }
            }

            if (!validMap)
            {
                BoltLog.Error("Invalid configuration: please verify level name");
                Application.Quit();
            }

            // Запустите сервер
            BoltLauncher.StartServer();
            DontDestroyOnLoad(this);
        }

        /// <summary>
        /// Вспомогательная функция для определения, запущена ли игра в безголовом режиме.
        /// </summary>
        /// <returns><c>true</c>, если использовался безголовый режим, <c>false</c> в противном случае.</returns>
        public static bool IsHeadlessMode()
        {
            return Environment.CommandLine.Contains("-batchmode") && Environment.CommandLine.Contains("-nographics");
        }

        static string GetArg(params string[] names)
        {
            var args = Environment.GetCommandLineArgs();
            for (int i = 0; i < args.Length; i++)
            {
                foreach (var name in names)
                {
                    if (args[i] == name && args.Length > i + 1)
                    {
                        return args[i + 1];
                    }
                }
            }

            return null;
        }
    }
}
```

Обычно он размещается в пустом GameObject на пустой сцене (которая будет использоваться только для сборок безголового сервера).

Скрипт был немного изменён для этого демо, чтобы соответствовать структуре проекта, и в настоящее время он размещён в пустом GameObject на сцене, находящейся в `Assets/Scenes/BoltHeadlessServer`.

#### Добавление проверок безголового сервера в вашу игру

Вышеупомянутый скрипт содержит статический вспомогательный метод под названием `IsHeadlessMode`, который используется для проверки, является ли запущенная игра безголовой. Если вы обновляете существующий проект, возможно, вы захотите добавить эту проверку, чтобы убирать или добавлять функции для безголового сервера, например не создавать персонажа игрока.

#### Настройки сборки

В `Buid Settings` проекта, добавьте сцену `BoltHeadlessServer` самой первой, чтобы сервер загружал её первой.

Затем выберите `Linux` в качестве целевой платформы и отметьте `Server Build`.

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-119e3c54e779d1120313d9dbba22037fbe3670ca%2Funity_photon_bolt_build_settings.png?alt=media" alt=""><figcaption></figcaption></figure>

Теперь вы можете собрать свою игру под Linux с указанными выше настройками.

Для **клиентских сборок**, не забудьте снять отметку с `BoltHeadlessServer` сцены и опции `IsServer` чтобы ваша игра работала корректно.

Для каждого шага, касающегося создания безголового сервера для Photon Bolt, дополнительные подробности доступны в [официальной документации](https://doc.photonengine.com/en-us/bolt/current/demos-and-tutorials/headless-server).

### Создайте контейнер для сервера

Если вы не знакомы с Docker или контейнерами, вы можете узнать больше, ознакомившись с [Что такое Docker?](https://docs.edgegap.com/ru/docs/tools-and-integrations/container/docker)

Чтобы создать контейнер из проекта Unity, обратитесь к [Unity на Docker](https://docs.edgegap.com/ru/docs/sample-projects/unity-netcodes/broken-reference).

### Добавьте ваше приложение в Edgegap

Теперь вы можете добавить свой контейнер в Edgegap, чтобы он размещался везде, где находятся ваши игроки.

Если вы не знаете, как добавить приложение в Edgegap, обратитесь к [руководству по интеграции](https://docs.edgegap.com/ru/learn/orkestraciya/application-and-versions).

Однако необходимо убедиться, что имя вашего приложения — `demo-game` и что у него есть версия под названием `v1`. Иначе вам нужно обновить эти значения в скрипте, расположенном в `Assets/Scripts/StaginController.cs`.

Также в `Assets/Scripts/StaginController.cs` скрипте вы найдёте константную переменную под названием `API_TOKEN`. Вам нужно создать токен в своём аккаунте Edgegap и вставить его строкой в эту переменную. Этот токен будет использоваться для авторизации API-запросов, отправляемых в Edgegap.

Вот соответствующий скрипт: токен из Edgegap выделен синим, а параметры приложения — красным:

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-356f4d51a5c114024fea432e8fcd9b677d3c9e98%2Funity_photon_bolt_staging_controller.png?alt=media" alt=""><figcaption></figcaption></figure>

## Игра в демо-версию

Наконец, вы можете запустить клиентскую сборку демо-игры, чтобы поиграть. Вы можете либо собрать клиентскую версию игры и запустить её, либо запустить прямо из интерфейса Unity. Просто убедитесь, что вы запускаете её на сцене `StartScene` .

После запуска появится интерфейс. Он содержит текстовое поле вверху, две большие кнопки и метку в левом нижнем углу экрана, показывающую текущее состояние Bolt.

<figure><img src="https://3845012722-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-3ace5ac3f2d80112f7564e85fdcf8c65d844bf34%2Funity_photon_bolt_demo_game.png?alt=media" alt=""><figcaption></figcaption></figure>

Вы можете скопировать свой API-токен из Edgegap в текстовое поле вверху. После вставки токена вы можете нажать кнопку `Request Server` для отправки API-запроса в Edgegap на запуск сервера.

Через несколько секунд вы должны увидеть метку внизу интерфейса с числом доступных серверов. Теперь нажмите кнопку `Connect to a random server` чтобы присоединиться к игре и начать играть.
