Список игровых серверов/комнат

Иногда бывает, что вам не нужна система запуска игровых серверов/комнат. Например, в игре Counter Strike игроки могли запускать сервер у себя на ПК и он появлялся в глобальном списке игровых серверов. Никаких "матчмейкингов" или "спаунеров". Все просто и быстро!

Данный фреймворк позволяет вам достичь такого же результата. Давайте узнаем как. 

Допустим вы создали вашу сетевую игру, используя uNet, Mirror Networking, Forge Remastered или другие системы создания многопользовательских игр.

У вас уже работает мультиплеерная логика и вы желаете запустить несколько игровых серверов для того, чтобы ваши игроки или тестеры смогли поиграть в вашу игру. Можно конечно разослать всем, кто будет играть, IP адреса и порты ваших игровых серверов. А можно воспользоваться системами данного фреймворка. Делается это простым способом. 

Создание сцены Мастер Сервера

Для начала вам необходимо создать пустую сцену и в ней создать пустой объект. Я назвал его --MASTER_SERVER, но вы можете назвать его как угодно. Добавьте к нему компонент MasterServerBehaviour. Можно оставить все настройки компонента по умолчанию. 

Далее вам необходимо добавить модули. Для этого создайте два пустых объекта как дочерние для нашего --MASTER_SERVER. Назовите один MatchmakerModule, а второй RoomsModule. К обоим объектам добавьте одноименные компоненты MatchmakerModule и RoomsModule соответственно. Настройки можно оставить по умолчанию.

Запустите вашу сцену в игровом режиме. Мастер сервер должен успешно запуститься и подключить все имеющиеся модули, в нашем случае это MatchmakerModule и RoomsModule. В консоли вывода информации, если все сделали правильно, вы должны увидеть следующее:

После успешной проверки вы можете собрать ваш мастер сервер с одной сценой, в которой вы создали все эти объекты и компоненты. После сборки создайте ярлык вашего мастер сервера и внесите все аргументы командной строки, которые вам необходимы. Обязательный аргумент, который запускает мастер сервер при старте это -mstStartMaster. О том как устанавливать аргументы командной строки подробно рассказано здесь. Сборку необходимо производить с установленным флажком Server Build. Это нужно для того, чтобы наш мастер сервер запускался в окне консоли. Подробнее можно узнать здесь.

 

Вот и все, мастер сервер готов к регистрации ваших игровых серверов! Теперь переходим к программированию.

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

Настройка игрового сервера

Откройте сцену запуска вашего игрового сервера и выполните следующие действия:

Создайте пустой объект в сцене и назовите его, например, --MASTER_CONNECTION_HELPER. Прицепите к данному объекту компонент ClientToMasterConnector. В его настройках укажите IP адрес и порт подключения к мастер серверу. В нашем случае мы тестируем нашу логику локально, но если вы уже планируете запускать ваш мастер сервер на виртуальном выделенном сервере(VDS), то укажите в поле serverIp и в поле serverPort соответствующие параметры подключения. Также установите флажок connectOnStart, чтобы наше подключение выполнялось сразу после запуска. Эти данные вы можете также указать через аргументы командной строки.

Давайте протестируем наше соединения игрового сервера с мастером. Запустите наш мастер сервер, который мы собрали ранее. Затем запустите ваш игровой сервер в редакторе. На скриншоте ниже мы можем увидеть подключенного клиента.

Подключенный клиент и есть наш игровой сервер. Теперь давайте напишем код регистрации нашего игрового сервера в списке. Вы можете выполнить процесс регистрации игрового сервера в списке сразу же после того, как вы его запустили и он успешно подключится к мастер серверу. В примере ниже показано как это сделать. 

using MasterServerToolkit.MasterServer;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Aevien.Tutorials
{
    public class ServersListTutorial : MonoBehaviour
    {
        private RoomController roomController;

        // Start is called before the first frame update
        void Start()
        {
            ClientToMasterConnector.Instance.Connection.AddConnectionListener(OnConnectedToMasterServerHandler, true);
            ClientToMasterConnector.Instance.Connection.AddDisconnectionListener(OnDisconnectedFromMasterServerHandler, false);
        }

        private void OnConnectedToMasterServerHandler()
        {
            RoomOptions options = new RoomOptions
            {
                IsPublic = true,
                // Your Game Server Name
                Name = "My Game With Friends",
                // If you want your server to be passworded
                Password = "",
                // Machine IP the server is running on
                RoomIp = "127.0.0.1",
                // Port of the game server
                RoomPort = 7777,
                // The max number of connections
                MaxConnections = 10
            };

            Mst.Server.Rooms.RegisterRoom(options, (controller, error) =>
            {
                if (!string.IsNullOrEmpty(error))
                {
                    Debug.LogError(error);
                    return;
                }

                roomController = controller;

                Debug.Log("Our server was successfully registered");
            });
        }

        private void OnDisconnectedFromMasterServerHandler()
        {
            Mst.Server.Rooms.DestroyRoom(roomController.RoomId, (isSuccess, error) =>
            {
                // Your code here...
            });
        }
    }
}
  • В методе Start() мы регистрируем прослушку событий подключения к мастер серверу.
  • В методе OnConnectedToMasterServerHandler мы создаем опции нашего игрового сервера и передаем их в запрос регистрации игрового сервера.
  • Обратным ответом на наш запрос мы получаем RoomController, который хранит информацию о зарегистрированном сервере, а также информацию об ошибках, если что то пошло не так.
  • В методе OnDisconnectedFromMasterServerHandler мы выполняем нашу логику, которую необходимо отработать в случае потери соединения с мастер сервером.

Если мы запустим наш игровой сервер с этим скриптом, то увидим следующее:

А в консоли мастер сервера будет выведена такая информация:

Переходим к клиентской части

Итак, мастер сервер работает и принимает игровые сервера к регистрации. Игровой сервер успешно регистрируется. Далее нам необходимо получить список игровых серверов на стороне клиента, когда игрок открывает окно выбора списка серверов. При открытии данного окна или при нажатии кнопки обновления списка серверов мы можем направлять запрос к мастеру следующим образом:

Mst.Client.Matchmaker.FindGames((games) =>
{
    canvasGroup.interactable = true;

    if (games.Count == 0)
    {
        statusInfoText.text = "No games found! Try to create your own.";
        return;
    }

    statusInfoText.gameObject.SetActive(false);
    DrawGamesList(games);
});

Вышеприведенный код взят из класса GamesListView. Это компонент вывода списка игровых серверов. Вытащите этот компонент в сцену из папки MasterServerToolkit > Bridges > Shared > Prefabs > UI. Уберите флажок HideOnStart в инспекторе компонента GamesListView. Запустите игровой режим и в окне нажмите кнопку UpdateList. В списке серверов вы увидите ваш с параметрами, которые вы установили при регистрации игрового сервера.

При нажатии на элемент списка вы выполните команду:

MatchmakingBehaviour.Instance.StartMatch(gameInfo);

Эта команда должна выполнять вашу логику подключения к игровому серверу. Вы легко можете перегрузить этот метод.

Вот вы и узнали как регистрировать ваш игровой сервер в списке. Но что если вы хотите создать так называемый "матчмейкинг"? Об этом мы поговорим в этом руководстве.