Мои Уведомления
Привет, !
Мой Аккаунт Мои Финансы Мои Подписки Мои Настройки Выход
Руководство API скрипты

Расширенная синхронизация состояний

Важно: UNet — это устаревшее решение, а также новая многопользовательская и сетьсистема Unity, которая обеспечивает многопользовательскую игру. игры через компьютерную сеть. Подробнее
См. в Словарь
Решение (Netcode для GameObjects) находится в разработке. Дополнительную информацию и дальнейшие действия см. на веб-сайте Unity Netcode for GameObjects.

В большинстве случаев использования SyncVars достаточно для скриптов вашей игрыфрагмента кода, позволяющего создавать собственные Компоненты, запускать игровые события, изменять свойства Компонентов с течением времени и реагировать на действия пользователя любым удобным для вас способом. Подробнее
См. в Словарь
, чтобы сериализовать их состояние для клиентов. Однако в некоторых случаях вам может потребоваться более сложный код сериализации. Эта страница предназначена только для опытных разработчиков, которым нужны индивидуальные решения для синхронизации, выходящие за рамки обычной функции Unity SyncVar.

Пользовательские функции сериализации

Чтобы выполнить свою собственную сериализацию, вы можете реализовать виртуальные функции в NetworkBehaviour, которые будут использоваться для сериализации SyncVar. Вот эти функции:

public virtual bool OnSerialize(NetworkWriter writer, bool initialState); public virtual void OnDeSerialize(NetworkReader reader, bool initialState);

Используйте флаг initialState, чтобы различать первый раз GameObject Основной объект в сценах Unity, который может представлять персонажей, реквизит, декорации, камеры, путевые точки и многое другое. Функциональность GameObject определяется прикрепленными к нему компонентами. Подробнее
См. в Словарь
сериализуется и когда можно отправлять добавочные обновления. Когда GameObject отправляется клиенту в первый раз, он должен включать в себя полный снимок состояния, но последующие обновления могут сэкономить полосу пропускания за счет включения только добавочных изменений. Обратите внимание, что функции ловушки SyncVar не вызываются, когда initialState имеет значение true; они вызываются только для добавочных обновлений.

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

Функция OnSerialize должна возвращать значение true, чтобы указать, что необходимо отправить обновление. Если он возвращает true, грязные биты для этого скрипта обнуляются. Если он возвращает false, грязные биты не изменяются. Это позволяет накапливать несколько изменений сценария с течением времени и отправлять их, когда система готова, а не каждый кадр.

Процесс сериализации

GameObjects с прикрепленным компонентом Network Identity может иметь несколько сценариев, полученных из NetworkBehaviour. Порядок сериализации этих GameObjects следующий:

На сервере:

  • У каждого NetworkBehaviour есть грязная маска. Эта маска доступна внутри OnSerialize как syncVarDirtyBits.

  • Каждой SyncVar в сценарии NetworkBehaviour назначается бит в грязной маске.

  • Изменение значения SyncVar приводит к установке бита для этой SyncVar в грязной маске

  • В качестве альтернативы вызов SetDirtyBit() записывает непосредственно в грязную маску

  • NetworkIdentityСетевой компонент, который позволяет назначать идентификатор вашему игровому объекту, чтобы сеть распознавала его как Игровой объект локального игрока или игровой объект только для сервера. Подробнее
    См. в Словарь
    Игровые объекты проверяются на сервере как часть его цикла обновления< /p>

  • Если какие-либо NetworkBehaviours в NetworkIdentity неверны, то UpdateVars Пакет создается для этого GameObject

  • Пакет UpdateVars заполняется вызовом OnSerialize для каждого NetworkBehaviour в GameObject

  • NetworkBehaviours, которые не являются грязными, записывают в пакет нули для своих грязных битов

  • NetworkBehaviours, которые являются грязными, записывают свою грязную маску, затем значения для измененных SyncVars

  • Если OnSerialize возвращает true для NetworkBehaviour, грязная маска сбрасывается для этого NetworkBehaviour, поэтому он не будет отправляться снова, пока его значение не изменится.

  • Пакет UpdateVars отправляется готовым клиентам, которые наблюдают за GameObject

На клиенте:

  • для GameObject получен пакет UpdateVars

  • Функция OnDeserialize вызывается для каждого сценария NetworkBehaviour в GameObject

  • Каждый скрипт NetworkBehaviour в GameObject считывает грязную маску.

  • Если грязная маска для NetworkBehaviour равна нулю, функция OnDeserialize возвращает значение без дальнейшего чтения

  • Если грязная маска имеет ненулевое значение, функция OnDeserialize считывает значения для SyncVars, соответствующие установленным грязным битам

  • Если есть функции-ловушки SyncVar, они вызываются со значением, считанным из потока.

Итак, для этого скрипта:

public class data : NetworkBehaviour { [SyncVar] public int int1 = 66; [SyncVar] public int int2 = 23487; [SyncVar] public string MyString = "Example string"; }

В следующем примере кода демонстрируется сгенерированная функция OnSerialize:

public override bool OnSerialize(NetworkWriter writer, bool forceAll) { if (forceAll) { // The first time a GameObject is sent to a client, send all the data (and no dirty bits) writer.WritePackedUInt32((uint)this.int1); writer.WritePackedUInt32((uint)this.int2); writer.Write(this.MyString); return true; } bool wroteSyncVar = false; if ((base.get_syncVarDirtyBits() & 1u) != 0u) { if (!wroteSyncVar) { // Write dirty bits if this is the first SyncVar written writer.WritePackedUInt32(base.get_syncVarDirtyBits()); wroteSyncVar = true; } writer.WritePackedUInt32((uint)this.int1); } if ((base.get_syncVarDirtyBits() & 2u) != 0u) { if (!wroteSyncVar) { // Write dirty bits if this is the first SyncVar written writer.WritePackedUInt32(base.get_syncVarDirtyBits()); wroteSyncVar = true; } writer.WritePackedUInt32((uint)this.int2); } if ((base.get_syncVarDirtyBits() & 4u) != 0u) { if (!wroteSyncVar) { // Write dirty bits if this is the first SyncVar written writer.WritePackedUInt32(base.get_syncVarDirtyBits()); wroteSyncVar = true; } writer.Write(this.MyString); } if (!wroteSyncVar) { // Write zero dirty bits if no SyncVars were written writer.WritePackedUInt32(0); } return wroteSyncVar; }

В следующем примере кода демонстрируется функция OnDeserialize:

public override void OnDeserialize(NetworkReader reader, bool initialState) { if (initialState) { this.int1 = (int)reader.ReadPackedUInt32(); this.int2 = (int)reader.ReadPackedUInt32(); this.MyString = reader.ReadString(); return; } int num = (int)reader.ReadPackedUInt32(); if ((num & 1) != 0) { this.int1 = (int)reader.ReadPackedUInt32(); } if ((num & 2) != 0) { this.int2 = (int)reader.ReadPackedUInt32(); } if ((num & 4) != 0) { this.MyString = reader.ReadString(); } }

Если NetworkBehaviour имеет базовый класс, который также имеет функции сериализации, следует также вызывать функции базового класса.

Обратите внимание, что пакеты UpdateVar, созданные для обновлений состояния GameObject, могут быть агрегированы в буферах перед отправкой клиенту, поэтому один пакет транспортного уровня может содержать обновления для нескольких GameObjects.

Вы можете отблагодарить автора, за перевод документации на русский язык. ₽ Спасибо
Руководство Unity 2021.3