Важно: 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
в GameObjectNetworkBehaviours
, которые не являются грязными, записывают в пакет нули для своих грязных битов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.