Многопользовательские игры через 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 раз.