Создание простой онлайн-игры с комнатами и синхронизацией
Введение SyncHubCloud — это мощное и гибкое SDK для Unity, разработанное для интеграции облачных сервисов в игровые и интерактивные проекты. Этот инструмент позволяет разработчикам легко подключаться
Этот урок охватывает весь цикл создания простой онлайн-игры на Unity с использованием SyncHubCloud: от подключения к серверу до синхронизации движения персонажей между клиентами.
И так, мы уже знаем как подключаться к своему облачному серверу по токену доступа, давайте теперь сделаем простую онлайн игру с комнатами и синхронизацией позиций и поворотов
Сцена Menu
Переименуйте сцену в которой мы подключаемся к облачному серверу на “Menu”
Создайте на сцене поле для ввода текста UI InputFiled и назовите его “InputFieldNameRoom”
Создайте на сцене 2 кнопки UI Button и назовите их “ButtonCreateRoom” и “ButtonGetRooms”
Вот что по итогу у нас должно получиться:
Создайте скрипт “RoomsManager” и пустой объект на сцене “RoomsManager”, добавьте скрипт на этот объект
Откроем скрипт RoomsManager и напишем код для создания комнаты
using UnityEngine;
using UnityEngine.UI;
using SyncHubCloud;
public class RoomsManager : MonoBehaviour
{
// Поле для ввода названия комнаты
public InputField InputFieldNameRoom;
// Кнопка создания комнаты
public Button ButtonCreateRoom;
void Start()
{
//Назначаем событие на кнопку создания комнаты
ButtonCreateRoom.onClick.AddListener(CreateRoom);
}
public void CreateRoom ()
{
// Проверяем подключены ли мы к серверу
if(SyncHub_ConnectionManager.Instance.IsConnected)
{
// Проверяем ввели ли мы название комнаты
if(string.IsNullOrEmpty(InputFieldNameRoom.text) == false)
{
/* Создаём комнату, первый параметр её название, второй параметр название сцены для неё и третий
максимальное количество игроков */
SyncHub_ConnectionManager.Instance.CreateRoom(InputFieldNameRoom.text, "Game", 5);
}
}
}
}
Назначим объекты в инспектор скрипта “RoomsManager“
Теперь давайте запустим и попробуем создать комнату. Для этого введём её название и нажмём кнопку “Создать комнату”
В результате мы получаем ошибку
Так и должно быть, потому что мы ещё не создали сцену “Game” и SynHubCloud ругается на это
Давайте создадим простенькую цену Game и добавим на неё объект 3D Plane, это будет наш пол
Обязательно добавьте сцену в сборку проекта
Снова запустим сцену Menu и попробуем создать комнату, вводим название комнаты и нажимаем создать комнату и нас сразу перебрасывает в сцену Game, после того как комната создалась на сервере
Сейчас наша сцена Game пустая, давайте теперь создадим простейшего персонажа, для этого создайте 3D объект капсулу и назовём её “Player”, это будет наш персонаж
Теперь добавим на объект Player скрипт SyncHub_ConnectionView (он уже есть в плагине SyncHub Cloud), этот скрипт нужно добавлять на все объекты которые будут синхронизироваться в режиме реального времени или принимать сообщения
Далее, создадим управление персонажем. Для этого создайте скрипт PlayerController.cs и напишите простейший код управления
using UnityEngine;
public class PlayerController : MonoBehaviour
{
//Скорость перемещения игрока
public float SpeedMove = 5f;
void Update()
{
// перемещение вперёд - назад
transform.position += Vector3.forward * SpeedMove * Input.GetAxis("Vertical") * Time.deltaTime;
// перемещение влево - вправо
transform.position += Vector3.right * SpeedMove * Input.GetAxis("Horizontal") * Time.deltaTime;
}
}
16.Добавьте скрипт PlayerController.cs на объект Player чтобы у нас получилось вот так
Теперь нам нужно из объекта Player сделать префаб, этот префаб будет использоваться для спавна всех игроков. Создайте в папке Assets папку SyncHubPrefabs и перенесите в эту папку объект Player, после удалите со сцены объект Player. Вот что у нас по итогу получится
И так, у нас есть уже игровой персонаж с управлением и он занесён в префаб, теперь нам нужно спавнить префаб игрока при подключении к комнате. Создайте скрипт GameManager.cs. На сцене создайте объект GameManager и добавьте на него созданный скрипт. Должно получится вот так:
Спавн игроков через GameManager
Теперь отредактируем скрипт
GameManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SyncHubCloud;
public class GameManager : MonoBehaviour
{
//Массив префабов персонажей игроков аттриубт "SyncHubPrefabPlayers" ОБЯЗАТЕЛЕН!
[SyncHubPrefabPlayers]
public List<GameObject> PrefabsPlayer = new List<GameObject>();
//Массив префабов объектов аттриубт "SyncHubPrefabObjects" ОБЯЗАТЕЛЕН!
[SyncHubPrefabObjects]
public List<GameObject> PrefabsGameObjects = new List<GameObject>();
//Индекс нашего персонажа в массиве, на случай если у вас будет много разных персонажей в игре
public int MyIndexPlayer;
// Переменная для хранения нашего заспавненного персонажа
public GameObject MyPlayerGM;
private void Awake()
{
// Загружаем номер индекса персонажа который вы можете указать меню
// (не обязательно, если у вас 1 префаб персонажа в массиве)
MyIndexPlayer = PlayerPrefs.GetInt("SelectedIndexPlayer");
}
private void OnEnable()
{
// Подписываемся на событие когда всех игроков в комнате заспавнило кроме нашего
SyncHub_ConnectionManager.OnSpawnedPlayers += OnSpawnedPlayers;
}
// отписываемся от всех событий при выходе из game сцены
private void OnDisable()
{
SyncHub_ConnectionManager.OnSpawnedPlayers -= OnSpawnedPlayers;
}
private void OnSpawnedPlayers()
{
//получаем префаб персонажа из нашего массива
GameObject myPlayerPrefab = PrefabsPlayer[MyIndexPlayer];
//спавним нашего персонажа
MyPlayerGM = SyncHub_ConnectionManager.Instance.SpawnMyPlayer(myPlayerPrefab, new Vector3(myPlayerPrefab.transform.position.x + Random.Range(-4, 4), myPlayerPrefab.transform.position.y, myPlayerPrefab.transform.position.z + Random.Range(-4, 4)));
}
}
Добавляем префаб нашего персонажа в GameManager

Запускаем сцену Menu и создаём комнату, после нас перекидывает в сцену Game и мы видим такой результат:
У нас создался экземпляр префаба нашего персонажа после создания и подключения к комнате и мы можем им управлять.
Подключение к уже существующим комнатам
Что же, отлично, мы уже умеем создавать комнату и спавнить персонажей на сцене. Теперь нам нужно научиться подключаться к уже созданной комнате. Для этого вернёмся на сцену Menu. Создайте в нашем уже существующем Canvas объект UI ScrollView и назовите его ScrollViewListRooms, в этом скролле мы будем отображать список текущих комнат
Разверните ScrollViewListRooms и в дочернем элементе создайте кнопку UI Button и назовите её ButtonRoom. Этот элемент как раз и будет кнопкой с описанием комнаты по нажатию на который мы будем подключаться к уже созданной комнате
Теперь напишем скрипт для кнопки комнаты, для этого создайте скрипт
ButtonRoom.cs
и напишите в нём такой код
using UnityEngine;
using UnityEngine.UI;
using SyncHubCloud;
public class ButtonRoom : MonoBehaviour
{
//Переменная текста наименования комнаты
public Text TextDescriptionRoom;
public void SetDataRoom (string _nameRoom, int _currentPlayers, int _maxPlayers)
{
//Добавляем описание комнаты
TextDescriptionRoom.text = string.Format($"Название комнаты: {_nameRoom} | Игроки: {_currentPlayers}/{_maxPlayers}");
//Добавляем событие по клику кнопки на которой висит этот скрипт
this.GetComponent<Button>().onClick.AddListener(delegate { ConnectToRoom(_nameRoom); });
}
public void ConnectToRoom (string _nameRoom)
{
//Подключаемся к комнате
SyncHub_ConnectionManager.Instance.ConnectRoom(_nameRoom);
}
}
Откройте префаб ButtonRoom и добавьте на него скрипт ButtonRooms.cs, а после занесите текст кнопки в переменную скрипта
Создайте в Assets папку MenuPrefabs и занесите эту кнопку в префаб, а после удалите эту кнопку из Content на сцене
Вернёмся теперь к скрипту RoomsManager.cs, откроем его и допишем следующий код
using UnityEngine;
using UnityEngine.UI;
using SyncHubCloud;
public class RoomsManager : MonoBehaviour
{
// Поле для ввода названия комнаты
public InputField InputFieldNameRoom;
// Кнопка создания комнаты
public Button ButtonCreateRoom;
//Объект внутри которого будем спавнить кнопки комнат
public Transform ContentScrollRect;
// Кнопка для запроса текущих комнат на сервере
public Button ButtonGetRooms;
// Кнопка - префаб которую мы создали для вывода информации о комнатах
public GameObject ButtonRoomPrefab;
void Start()
{
//Назначаем событие на кнопку создания комнаты
ButtonCreateRoom.onClick.AddListener(CreateRoom);
//Назначаем событие на кнопку для запроса комнат
ButtonGetRooms.onClick.AddListener(UpdateListRooms);
}
private void OnEnable()
{
//Подписываемся на событие получения списка комнат
SyncHub_ConnectionManager.OnGetRooms += OnGetRooms;
}
//Отписываемся от всех событий
private void OnDisable()
{
SyncHub_ConnectionManager.OnGetRooms -= OnGetRooms;
}
private void OnGetRooms(SyncHub_ConnectionManager.RootRooms _rooms)
{
for (int i = 0; i < _rooms.Data.Count; i++)
{
// Спавним кнопку в списке
GameObject buttonRoom = Instantiate(ButtonRoomPrefab, ContentScrollRect);
// Заносим данные комнаты в скрипт кнопки
buttonRoom.GetComponent<ButtonRoom>().SetDataRoom(_rooms.Data[i].NameRoom, _rooms.Data[i].CurrentCountPlayers, _rooms.Data[i].CountMaxPlayers);
}
}
public void CreateRoom ()
{
// Проверяем подключены ли мы к серверу
if(SyncHub_ConnectionManager.Instance.IsConnected)
{
// Проверяем ввели ли мы название комнаты
if(string.IsNullOrEmpty(InputFieldNameRoom.text) == false)
{
/* Создаём комнату, первый параметр её название, второй параметр название сцены для неё и третий
максимальное количество игроков */
SyncHub_ConnectionManager.Instance.CreateRoom(InputFieldNameRoom.text, "Game", 5);
}
}
}
public void UpdateListRooms ()
{
// Запрашиваем у сервера список комнат
SyncHub_ConnectionManager.Instance.GetListRooms();
}
}
Вернитесь в сцену Menu и занесите переменные в инспектор
Давайте теперь соберём сборку для Windows и запустим 2 клиента сразу. Заходим в File -> Build Settings, далее выбираем платформу Windows, потом заходим в Player Settings и устанавливаем оконный режим, что бы было нагляднее
После сборки проекта, запустите 2 экземпляра клиента
Создайте на одном из клиентов комнату
На клиенте на котором была создана комната, мы попали в Game сцену
Теперь на клиенте слева нажмите кнопку получить список комнат и у нас появится кнопка созданной комнаты, нажмите на неё, таким образом вы подключитесь к комнате созданной другим игроком (в данном случае Вами)
После того как Вы подключились созданной комнате, Вы увидите примерно вот такую картину
Если Вы попробуете управлять персонажем, то заметите что перемещаются оба префаба, хотя должен только Ваш персонаж (такое происходит потому что скрипт контроллера PlayerController.cs висит на 2 экземплярах префаба), исправить проблему поможет SyncHub_ConnectionView.IsMine(). Откройте скрипт PlayerController.cs и допишите такие строки:
using SyncHubCloud;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
// переменная нашего скрипта SyncHub_ConnectionView который уже висит на префабе Player
public SyncHub_ConnectionView syncHub_ConnectionView;
//Скорость перемещения игрока
public float SpeedMove = 5f;
void Update()
{
// проверка если это наш префаб игрока
if (syncHub_ConnectionView.IsMine())
{
// перемещение вперёд - назад
transform.position += Vector3.forward * SpeedMove * Input.GetAxis("Vertical") * Time.deltaTime;
// перемещение влево - вправо
transform.position += Vector3.right * SpeedMove * Input.GetAxis("Horizontal") * Time.deltaTime;
}
}
}
Добавьте компонент SyncHub_ConnectionView.cs в переменную syncHub_ConnectionView на префабе Player
Снова сделайте сборку и повторите запуск двух экземпляров клиента и после, увидите что, Вы можете управлять только своим персонажем. Но теперь у нас другая проблема, мы не видим перемещения позиции другого игрока
Для этого нам нужно синхронизировать позиции игроков, есть несколько вариантов как это сделать, но самый простой и рекомендуемый, использовать компонент SyncHub_SyncTransfrom.cs (Он есть в плагине SyncHub Cloud). Для этого выделите префаб Player и добавьте на него скрипт SyncHub_SyncTransfrom.cs (ВАЖНО, там где Вы будете использовать SyncHub_SyncTransfrom.cs обязательно должен присутствовать SyncHub_ConnectionView.cs). После его добавления, Вы увидите вот такие настройки:
Давайте их разберём чуть подробнее:
IsSyncPosition
- Если нужна синхронизация позицийIsSyncRotation
- Если нужна синхронизация поворотаIsSyncScale
- Если нужна синхронизация скейла (размера)TypeInterpolationPos, TypeInterpolationRot, TypeInterpolationScale
- Тут Вы выбираете тип интерполяции, имеются такие настройки:Lerp
- Линейная интерполяция между двумя точками с плавным “торможение” к последней полученным значениямMoveTowards
- Интерполяция без плавного “торможения” к последним полученным значениямInstantly
- Жёсткая привязка к последним полученным данным без интерполяции (плавного перемещения, поворота и т.д.)Укажем такие настройки:
Снова соберите сборку и запустите два экземпляра клиента. Теперь Вы увидите, что при управлении своим персонажем, его позиция синхронизируется с позицией префаба на другом клиенте
На этом урок по созданию простой онлайн игры завершён. Вы научились из этого урока:
Как подключаться к серверу по токену
Как создавать комнату
Как получать список комнат и подключаться к ним
Как спавнить своего персонажа
Как спавнить персонажей которые уже есть в комнате
Как спавнить нового персонажа другого игрока который подключился к комнате
Как определить кому принадлежит экземпляр префаба
Как синхронизировать позиции, повороты и скейлы
В следующем уроке мы разберём RPC и Stream в SyncHubCloud — ключ к удалённым вызовам и потоковой передаче данных.
Last updated
Was this helpful?