Dmitry Koblyk, CTO, Panzerdog
Talk about main aspects of client-server multiplayer engine development solutions based on Unity3D for “Tacticool” mobile action game. #MadeWithUnity
26. AbstractSyncComponent
На стороне сервера на каждом тике определяет нужно ли слать
данные о себе на клиент.
На стороне клиента на каждом кадре интерполирует между
полученными данными.
Всем привет! Меня зовут Дмитрий и я работаю в кампании Panzerdog над игрой Tacticool. Сегодня я попробую рассказать о том как мы делали мультиплеер в нашей игре. Если коротко, то Тактикул – это мобильный шутер с короткими матчами 5 на 5. Думаю после просмотра видео станет более понятно, что из себя представляет игра.
На мой взгляд от управление в игре очень сильно влияет на то как вы будете писать сетевой код.
В нашей игре персонаж всегда бежит вперед. Как в раннере. Экран разделен на две части: игрок нажимает на левую часть экрана – персонаж начинает поворачивать влево, на правую – вправо. Все просто. Также в правом нижнем углу есть одна кнопка – применить абилку. Абилкой может быть бросок гранаты или выстрел из рпг, например.
Все началось с этой фразы.
После пары-тройки отстойных прототипов стало понятно, что мы хотим сделать игру с синхронным мультиплеером и не пошаговую. Да, мы пробовали сделать управление машиной пошаговым.
Позже конечно же концепция «игры про машинки» эволюционировала. Игрок больше не управлял машиной, теперь игрок управляет персонажем и сам решает хочет ли он садиться в машину или нет.
Я не могу не упомянуть этот блог. Он помог мне разобраться с чего же начать писать сетевой код и прояснил очень много вопросов.
В нашей игре максимально глупый клиент. Можно сказать, что клиент это просто плеер, который проигрывает данные полученные от сервера и шлет на сервер пользовательский ввод. Сервер же в свою очередь занимается обработкой пользовательского ввода и симуляцией игрового мира.
В нашей игре мы выбрали частоту отправки данных 30 раз в секунду. Т.е клиент отправляет на сервер инпуты 30 раз в секунду и получает от сервера состояние игрового мира с частотой 30 раз в секунду.
Рассмотрим на кубиках как будет работать клиент. Самая наивная реализация это применять самый свежий снэпшот. С левой стороны показано как выглядит мир на сервере, справа на клиенте.
Пусть клиент всегда находится в прошлом относительно сервера. Например на 100мс
Вместо того чтобы применять снэпшот как только он пришел будем сохранять его в буффер. И когда нам нужно будет обновить игровой мир в нашем буфере можно будет найти два снэпшота между которыми можно интерполировать данныем.
TCP гарантирует, что данные будут доставлены и в том порядке в котором были отправлены. Грубо говоря TCP представляет из себя поток данных в который можно писать и из которого можно читать. На низком уровне при отправке данных TCP разбивает их на пакеты и шлет нужному адресату. Проблемы возникают в тот момент когда какой-нибудь пакет теряется. Возникает большая пауза пока TCP не поймет, что пакет потерялся, перепошлет его и так далее. Во время этой паузы невозможно получить новые данные до тех пор пока TCP не удостовериться что потерянный пакет пришел. Это может занять секунды.
UDP наш выбор.
Примерно в тот момент, когда мы начали делать игру Unity выпустила UNET. Это библиотека которая упрощает синхронизацию данных.
Обычно ее разбивают на два слоя – низкий уровень и высокий. Низкий уровень умеет держать соединение между двумя устройствами и обмениваться данными между ними с помощью UDP. Также стоит отметить, что в UNET реализован Reliable UDP. На высшем же уровне доступны такие концпции как синхронизация Transforma или отдельных переменных, вызов функций с сервера и т.д. В тактикуле мы используем только возможности низшего уровня, чтобы иметь как можно больше контроля над происходящим.
Посчитаем время, которое проходит между применением игроком какого-либо действия и отображением результата на это действие.
В шутерах используется такой способ как предсказания. Клиент мнгновенно обрабатывает действия игрока, а сервер потом корректирует состояние игрового мира. Почему не получается делать предсазания в нашей игре. Проблема предсказаний в том что клиент не может предсказать как поведут себя другие игроки.