Полезное

Мы Вконтакте

Discord канал

#
Аватара пользователя
Пользователь
Сообщения: 40
Обзор работы с сетями.

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

Онлайн система UE4 строится вокруг клиент/серверной модели. Это означает, что есть один авторитарный (значит, что только информация сервера о состоянии игры является единственно правильной) сервер, который принимает подключения от клиентов и раздает им актуальную информацию о мире игры.

Акторы.

В одиночной игре акторы используются для отображения всевозможных сущностей в игре (статичная геометрия, скелетно-анимированная геометрия, физические объемы, триггеры и т.п.). В многопользовательской игре они исполняют такую же функцию, за исключением одного: все клиенты используют «тень» актора, так сказать его копию, оригинал которого существует у авторитарного сервера.

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

Пример репликации.

Прим. пер. : Репликация – в сетевой терминологии, процесс воссоздания чего-то, с одного компьютера на другом в режиме реального времени. Например, когда вы смотрите онлайн концерт, то звук и изображение реплицируется, но управлять концертом вы не в состоянии.

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

Вы можете видеть врагов, потому что сервер обнаружил, что враги уместны в вашей сцене (потому что они попали в зону вашей видимости) и с этого момента сервер начал реплицировать этих акторов на ваш компьютер. Таким образом, вы (как клиент) имеете локальные копии двух врагов. Вы можете видеть, что они бегут к вам, потому что сервер реплицирует их свойства Location и Velocity. Вы слышите звуки выстрелов, потому что сервер реплицирует функцию ClientHearSoun. Это означает, что функция ClientHearSound вызывается для вашего PlayerPawn когда сервер считает, PlayerPawn слышит звуки.

К этому моменту, низкоуровневые механизмы, которыми оперирует Unreal Engine для многопользовательских игр должны быть вам понятны. Сервер обновляет состояние игры и принимает все игровые решения. Сервер реплицирует клиентам акторы, переменные-свойства и функции, которые вызываются у клиентов.

Так же вам должно быть понятно, что не все акторы обязаны реплицироваться. Например, если актор ушел от вас далеко-далеко, за пределы вашей видимости, то нет никакого смысла реплицировать его на вашем компьютере, т.к. тем самым вы только будете зря нагружать свою сеть мусорным траффиком. Аналогично, не все переменные требуют репликации. Например, если сервер использует какие-то переменные для принятия решения вашим искусственным интеллектом, то клиенту они совсем ни к чему, ему важно само решение вашего искусственного интеллекта. Ну и как вы догадались, не все функции клиента должны вызываться сервером. Только те функции, которые уведомляют клиента о том, что он что-то увидел или услышал, интересны локальному игроку. Итак, сервер содержит огромное количество информации и только малая ее доля интересна клиентам, та доля, которая связана с тем, что конкретный клиент видит, слышит или чувствует.

Таким образом, мы подходим к следующему вопросу: «Как Unreal Engine знает какие акторы, переменные и функции нужно реплицировать?».

Ответ прост: «Только то, что явно обозначено в коде или через Bluprint’ы, как replicated».
Аватара пользователя
Пользователь
Сообщения: 40
Многопользовательские игры через Blueprints.

Общее.

Unreal Engine 4 предоставляет много многопользовательских инструментов «из коробки». Кроме того, многое для многопользовательской игры реализовано в классе Character и CharacterMovementComponent, которые вы можете свободно использовать в своих проектах.

Обзор инструментов

Для того, что бы добавить многопользовательский функционал в свою игру, нужно очень четко представлять роли основных классов движка и как они влияют на многопользовательскую игру:
  • GameInstance
  • GameMode
  • GameState
  • Pawn (и Character, который является наследником Pawn)
  • PlayerController
  • PlayerState

Вы можете изучить раздел документации «framework documentation» для подробного описания этих классов. Сейчас нам хватит запомнить следующие тезисы:
  • Ваш GameMode является объектом только сервера и используется только им.
  • Ваш GameState используется как сервером, так и клиентами (в режиме чтения), так что вы можете передавать GameState информацию об игре, которую смогут прочитать клиенты (например, оставшееся время игры).
  • Ваш PlayerController используется сервером для каждого игрока, присоединившегося к игре. На клиентах есть свои PlayerController, но только для самого себя, локального игрока. Это означает, что PlayerController не лучшее место для хранения свойств, которые вы хотите реплицировать между клиентами.
  • А вот PlayerState создается для каждого клиента подключенного к игре и видим любому игроку. Вот как раз из него можно реплицировать те свойства игрока, которые вы хотели бы показать остальным игрокам.
  • Pawns (в том числе Characters) тоже используются как на сервере, так и на клиентах, поэтому могут содержать любые свойства или события, для репликации. Отличие от PlayerState в том, что PlayerState хранит информацию о клиенте на протяжении всей игры, а вот Pawn может быть «убит» другим игроком и воссоздастся на точке «респауна» новеньким, потеряв все накопленные данные.

Репликация акторов
Изображение

Основа технологии многопользовательских игр в UE4 – репликация акторов. Если установлен флаг "Replicates", то актор будет автоматически синхронизироваться между сервером и всеми подключенными клиентами. Самое главное – понять, что акторы реплицируются только от сервера к клиенту и никак иначе. Вы, конечно, возразите, что клиенты тоже должны как-то посылать свои данные серверу. Для этого используются "Run on server" события.

Авторитарность

Акторы могут быть как частью только клиента, так и реплицированным актором сервера. Для того, что бы разделить эту функциональность, есть функция "Has Authority" и макрос "Switch Has Authority", с помощью которых можно разделить логику, применяемую к актору. Не забывайте, что клиент всегда авторитарен над акторами которые создал сам, а не получил репликацией от сервера.
Изображение

Переменные

В свойствах каждой переменной есть выпадающий список "Replication".
Изображение

  • None – значение по умолчанию. Данная переменная будет использоваться только на локальном компьютере.
  • Replicated – когда сервер будет реплицировать данного актора, то он будет рассылать значение этой переменной. Значение этой переменной будет меняться у игроков автоматически. Конечно, в реальной игре обновления происходят не совсем мгновенно и есть задержка сети. И не забывайте, что направление репликации только от сервера к клиенту. Если вы измените данную переменную на локальной машине, вы не увидите обновления у других клиентов.
  • RepNotify – переменная будет вести себя, как и при Replicated выборе, однако появится дополнительная OnRep_ функция в вашем Blueprint. Эта функция будет вызываться автоматически, когда значение переменной изменилось. Изображение

Спавн и уничтожение

Когда реплицируемый актор спавнится на сервере, то его копия автоматически создается на всех клиентах. Но, как мы помним, спавн актора на клиенте, не даст совершенно никакого эффекта ни на остальных клиентах, ни на сервере. Однако это не запрещает нам создавать акторов на клиенте, например для декоративных целей, которые не вляют на геймплей, когда точная репликация (например взрыва) не требуется для всех клиентов.

Ситуация аналогичная и для уничтожения актора. Уничтожение сервером, вызовет уничтожение копии на всех клиентах. Если клиент попытается уничтожить актора, над которым он не авторитарен, то запрос уничтожения проигнорируется. Основной тезис здесь такой же, как и при спавне: «Если нужно уничтожить реплицируемого актора, то уничтожайте его на сервере».

Репликация событий

В Blueprint помимо репликации акторов и их переменных, вы можете запускать события на клиенте и сервере.

Владельцы

Важная идея, которую нужно понять, работая с многопользовательским режимом и, особенно, с репликацией событий, состоит в том, что бы понимать, какой из подключившихся игроков является владельцем конкретного актора или компонента. Например, "Run on server" события могут быть вызваны только от акторов, которыми владеет какой-то конкретный клиент. Обычно это означает, что можно вызывать "Run on server" события только у следующих акторов:
  • Клиентский локальный PlayerController
  • Pawn в который вселен локальный PlayerController
  • Клиентский PlayerState.
Точно так же, для сервера нужно понимать какому клиенту отправлять "Run on owning client" события. Поэтому они могут быть вызваны только для вышеуказанных акторов.

События

В панели деталей, вашего custom event, можно выбрать метод репликации события.
Изображение

  • Not Replicated – значение по умолчанию, никакой репликации, если вызвано на сервере, то исполнится на сервере, если на клиенте, то на клиенте.
  • Multicast – если на сервере будет вызвано это событие, то оно вызовется на всех подключенных клиентах, независимо от того, кто владелец этого актора. Если будет вызвано на клиенте, то будет исполнено только на этом на клиенте.
  • Run on server – Если вызвано на сервере, то исполнится на сервере. Если будет вызвано клиентом, который владеет актором, то будет исполнено на сервере. Это главная возможность отправлять серверу данные от клиента.
  • Run on Owning Client - Если вызвано на сервере, то исполнится на клиенте, который владеет актором. Так как сервер может сам владеть актором, то "Run on Owning Client" может вызваться опять же на сервере. Если вызвано на клиенте, то будет исполнено только на клиенте, без репликации.

Итак, если событие будет вызвано на сервере и
  • Если актором владеет клиент, то Not replicated, Run on Server – вызовет событие на сервере, Multicast – на сервере и всех клиентах, а Run on Owning Client – на клиенте-владельце.
  • Если актором владеет сервер, то Not replicated, Run on Server, Run on Owning Client – вызовет событие на сервере, а Multicast – на сервере и всех клиентах.

Если событие будет вызвано на клиенте и
  • Если актором владеет вызывающий клиент, то Not replicated, Multicast, Run on Owning Client – вызовет событие на вызывающем клиенте, Run on Server – вызовет событие на сервере.
  • Если актором владеет другой клиент, то Not replicated, Multicast, Run on Owning Client – вызовет событие на вызывающем клиенте, Run on Server – будет проигнорированно.
  • Если актором владеет сервер, то Not replicated, Multicast, Run on Owning Client – вызовет событие на вызывающем клиенте, Run on Server – будет проигнорированно.

Как вы видите, любые события, которые вызываются у клиента и которые не "Run on Server" исполняются так, как-будто они не реплицированы.
Все это связано с тем, что клиенты не могут взаимодействовать напрямую, только через авторитарный сервер. Например, клиент не может сделать массовую (multicast) рассылку событий напрямую всем клиентам, он обязан попросить об этом сервер. Этого можно добиться, если использовать два реплицируемых события: одно "Run on server", а другое "Multicast". В реализации "Run on server" события можно сделать проверку допустимости действия, а затем вызвать "Multicast" событие.
Изображение

Прогресс игры при позднем соединении.

Рассмотрим, как работают описанные механизмы в случае, если игроки могут подключаться к игре не в самом ее начале. В случае, если игрок подключается к игре, то все события, которые происходили до него не могут быть вызваны. Поэтому все важное состояние игры необходимо хранить в виде реплицируемых переменных. Будет неплохо, если клиент, который совершает какое-то действие в мире, будет информировать об этом сервер "Run on server" событие, а сервер будет выставлять некоторые реплицируемые переменные, связанные с этим событием. Таким образом любой клиент, который только присоединился увидит результат изменения мира, независимо от того, как давно это произошло.

Прим. пер. : Например, если у вас есть сундук, то при его открытии вы можете сделать multicast событие о том, что сундук открывается и переменную «IsChestOpen» равной true. Тогда все текущие игроки увидят, что сундук открывается. А все новые игроки увидят только уже открытый сундук.

Надежность

Для любого реплицируемого события можно выбрать надежность доставки (reliable или unreliable).

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

Unreliable означает, что доставка события не гарантирована. Пакет может потеряться в сети и нет необходимости отправлять его повторно. Отличный выбор для событий, чья текущая важность не так велика. Например, если игрок из-за плохого соединения не увидел взрывы от снарядов, то нет смысла пытаться ему это событие взрыва гарантированно донести, потому что ценность этого события, спустя время, нулевая. А вот повреждения от взрыва, стоит реплицировать гарантировано, что бы внезапная смерть при полном здоровье не стало для игрока сюрпризом.
Последний раз редактировалось Груберк 05 июн 2015, 13:01, всего редактировалось 1 раз.
Аватара пользователя
Пользователь
Сообщения: 40
Клиент-Серверная модель

Общее.

Как мы помним, UE4 основан на клиент-серверной модели.

Сервер это важная часть UE4, настолько важная, что по сути в любой одиночной игре игрок по сути сам себе сервер. Кроме того, он содержит состояние игры, логику игры, подключения игроков, перемещения по картам и т.д.

По сути сервер содержит в себе весь наш геймплей. Кроме того, в задачи сервера входит уведомление клиентов о необходимости сменить карту, о том, что игра началась или окончилась и т.д.

Кратко коснемся некоторых нюансов, при работе со стандартными классами движка.

Состояние игры и собственно сама игра – GameMode актора. Только сервер содержит этого актора. Ни один клиент не содержит даже его копии. Для связи с клиентами, используется GameMode актор. Этого актора видят все клиенты и могут считывать его данные.

Connection Process

Для того, что бы игра состоялась, необходимо подключить к ней игроков.

Когда клиент подключается впервые, происходит несколько вещей. Для начала, клиент посылает запрос на подключение. Сервер получает запрос и если соединение допустимо (совпал пароль или другие критерии), то начинается магия игры.

Итак, по-порядку:
  1. Клиент посылает запрос на подключение.
  2. Подключение принято и сервер возвращает игроку название текущего уровня.
  3. Сервер ждет, пока игрок загрузит уровень.
  4. Когда уровень загрузился, то сервер вызывает AGameMode::PreLogin. В этот момент можно отменить соединение и отключить игрока.
  5. Если все успешно, то сервер вызывает AGameMode::Login. В этой функции создается PlayerController, который подменяет реализацию по умолчанию, используемую при процессе соединения. А так же новый PlayerController реплицируется с подключенным клиентом. Именно здесь будет вызван APlayerController::BeginPlay. Кроме того не стоит вызывать реплицируемые события в этот момент, следует подождать AGameMode::PostLogin.
  6. Теперь, если все успешно, то вызывается AGameMode::PostLogin. Теперь все отлично и можно пользоваться PlayerController на всю катушку.

Последний раз редактировалось Груберк 05 июн 2015, 13:38, всего редактировалось 2 раз(а).
Аватара пользователя
Пользователь
Сообщения: 40
Резерв3
Аватара пользователя
Пользователь
Сообщения: 40
Резерв4
Аватара пользователя
Пользователь
Сообщения: 40
Резерв5


Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 54

UEngine.ru © 2017
Все права защищены. При копировании материалов с сайта, ссылка на первоисточник обязательна.
Яндекс.Метрика
Главная страница