Типы данных
Клиент и сервер могут передавать данные друг другу через удаленные вызовы, синхронизацию состояний или через Network Messages
Mirror поддерживает ряд типов данных, которые вы можете использовать в них, такие как:
Базовые C# типы (byte, int, char, uint, UInt64, float, string, и т.д.)
Встроенные математические типы Unity (Vector3, Quaternion, Rect, Plane, Vector3Int, и т.д.)
Встроенные типы Unity, которые под капотом являются структурами (Color, Sprite, Texture2D, Ray, и т.д.)
URI
NetworkIdentity
,NetworkBehaviour
GameObject, но только с компонентом
NetworkIdentity
который был заспавнен в сетиНе prefab!
Смотрите важные подробности в секции GameObjects.
Структуры с любым из вышеперечисленных типов данных
Рекомендуется реализовать IEquatable, и пометить структуру как readonly, поскольку изменение одного из свойств не приводит к повторной синхронизации
Классы, у которых каждое поле имеет поддерживаемый тип данных
Они будут выделять мусор и будут создаваться заново в получателе при каждой отправке.
ScriptableObject, у которого каждое поле имеет поддерживаемый тип данных
Они будут выделять мусор и будут создаваться заново в получателе при каждой отправке.
Массивы любого из вышеперечисленных типов
Не поддерживается с SyncVars или Sync* collections
ArraySegments из любого из вышеперечисленных типов
Не поддерживается с SyncVars или Sync* collections
Game Objects
Game Objects в SyncVars, SyncLists, и SyncDictionaries в некоторых случаях хрупкие, и их следует использовать с осторожностью.
Пока игровой объект уже существует как на сервере, так и на клиенте, ссылка должна быть в порядке.
Когда данные синхронизации поступают на клиент, указанный игровой объект может еще не существовать на этом клиенте, что приводит к нулевым значениям в данных синхронизации. Tэто происходит потому, что внутри Mirror передает netId
из NetworkIdentity
и пытается найти его в клиентском словаре NetworClient.spawned
.
Если объект еще не был создан на клиенте, совпадение не будет найдено. Это может быть в той же полезной нагрузке, особенно для присоединения клиентов, но после синхронизации данных из другого объекта. Это также может быть значение null, поскольку игровой объект не является наблюдателем другого, Interest Management
.
Вы можете обнаружить, что синхронизировать данные более надежно через NetworkIdentity.netID
(uint). Вместо этого выполните свой собственный поиск в NetworkClient.spawned
чтобы получить объект, возможно, в корутине:
Пользовательские типы данных
Иногда вы не хотите, чтобы Mirror генерировал сериализацию для ваших собственных типов. Например, вместо сериализации всех данных вы можете захотеть сериализовать только идентификатор данных, и получатель сможет искать сведения о данных по идентификатору в предопределенном списке или базе данных.
Иногда вам может потребоваться сериализовать данные, которые используют другой тип, не поддерживаемый Mirror, например DateTime.
Вы можете добавить поддержку для любого типа, добавив методы расширения в NetworkWriter
и NetworkReader
. Например, чтобы добавить поддержку для DateTime
, добавьте это где-нибудь в свой проект:
...затем вы можете использовать DateTime
в ваших [Command]
или даже SyncList
Наследование и полиморфизм
Иногда вам может потребоваться отправить своим командам полиморфный тип данных. Mirror не сериализует имя типа, чтобы уменьшить размер сообщений и по соображениям безопасности, поэтому Mirror не может определить тип полученного объекта, просмотрев сообщение.
Этот код не работает "из коробки".
CmdEquip будет работать, если вы предоставите пользовательский сериализатор для типа Item
. К примеру:
ScriptableObjects
Люди часто хотят отправлять ScriptableObjects с клиента или сервера. Например, у вас может быть куча мечей, созданных как объекты, доступные для сценариев, и вы хотите поместить экипированный меч в syncvar. Это будет работать нормально, Mirror сгенерирует средства чтения и записи для объектов scriptable, вызвав ScriptableObject.Создайте экземпляр и скопируйте все данные.
Однако сгенерированные программы чтения и записи подходят не для каждого случая. ScriptableObjects часто ссылаются на другие ресурсы, такие как текстуры, Prefab'ы или другие типы, которые невозможно сериализовать. Объекты, доступные для написания сценариев, часто сохраняются в папке "Ресурсы". Скриптовые объекты иногда содержат в себе большой объем данных. Сгенерированные средства чтения и записи могут не работать или быть недостаточными для этих ситуаций.
Вместо передачи данных ScriptableObject вы можете передать имя, и другая сторона сможет выполнить поиск того же объекта по имени. Таким образом, вы можете иметь любые данные в вашем скриптовом объекте. Вы можете сделать это, предоставив пользовательские средства чтения и записи. Вот пример:
Last updated