Сериализация — это автоматический процесс преобразования структур данных или состояний объектов в формат, который Unity может сохранять и реконструировать позже. Некоторые встроенные функции Unity используют сериализацию; такие функции, как сохранение и загрузка, Инспекторокно Unity, в котором отображается информация о текущем выбранном игровом объекте, активе или настройках проекта, что позволяет вам проверять и редактировать значения. Дополнительная информация
Просмотр в окне Словарь, экземпляр и класс ПрефабыТип ресурса, позволяющий хранить игровой объект с компонентами и свойствами. Префаб действует как шаблон, из которого вы можете создавать новые экземпляры объектов на сцене. Подробнее
См. в Словарь. См. документацию по использованию встроенной сериализации для получения дополнительной информации обо всем этом.
То, как вы упорядочиваете данные в своем проекте Unity, влияет на то, как Unity сериализует эти данные, и может существенно повлиять на производительность вашего проекта. На этой странице рассказывается о сериализации в Unity и о том, как оптимизировать для нее ваш проект.
См. также документацию по ошибкам сериализации, пользовательской сериализации и Встроенная сериализация.
Что такое горячая перезагрузка
Горячая перезагрузка — это процесс создания или редактирования скриптовфрагмента кода, позволяющего создавать собственные компоненты, запускать игровые события, изменяйте свойства компонентов с течением времени и реагируйте на действия пользователя любым удобным для вас способом. Подробнее
См. в Словарь при открытом редакторе и немедленном применении поведения скрипта. Вам не нужно перезапускать приложение или редактор, чтобы изменения вступили в силу.
Когда вы изменяете и сохраняете сценарий, Unity перезагружает все текущие загруженные данные сценария. Сначала он сохраняет все сериализуемые переменные во всех загруженных скриптах, а после загрузки скриптов восстанавливает их. Все данные, которые нельзя сериализовать, теряются после горячей перезагрузки.
Сохранение и загрузка
Unity использует сериализацию для загрузки и сохранения сценСцена содержит среду и меню вашей игры. Думайте о каждом уникальном файле сцены как об уникальном уровне. В каждой сцене вы размещаете свое окружение, препятствия и декорации, по сути проектируя и создавая свою игру по частям. Подробнее
См. в Словарь, АктивыЛюбые медиафайлы или данные, которые можно использовать в вашей игре или проекте. Ресурс может быть получен из файла, созданного вне Unity, например, из 3D-модели, аудиофайла или изображения. Вы также можете создавать некоторые типы ресурсов в Unity, например контроллер аниматора, аудиомикшер или текстуру рендеринга. Подробнее
См. в Словарь и AssetBundles на жесткий диск вашего компьютера и обратно. Сюда входят данные, сохраненные в ваших собственных объектах API сценариев, таких как компоненты MonoBehaviour и ScriptableObjects.
Многие функции редактора Unity основаны на основной системе сериализации. При сериализации следует особенно помнить о двух вещах: окне инспектора и горячей перезагрузке.
Окно инспектора
При просмотре или изменении значения GameObjectфундаментальный объект в сценах Unity, который может представлять персонажей, реквизит, пейзажи, камеры, путевые точки и многое другое. Функциональность GameObject определяется прикрепленными к нему компонентами. Подробнее
См. в поле компонента Словарь в разделе окно инспектора, Unity сериализует эти данные, а затем отображает их в окне инспектора. Окно инспектора не взаимодействует с Unity Scripting API, когда оно отображает значения поля.
Если вы используете свойства в своем скрипте, ни один из методов получения и установки свойств никогда не вызывается при просмотре или изменении значений в окнах инспектора, поскольку Unity сериализует поля окна инспектора напрямую. Это означает, что: Хотя значения поля в окне Инспектора представляют свойства скрипта, изменения значений в окне Инспектора не вызывают какие-либо геттеры и сеттеры свойств в вашем скрипте
Правила сериализации
Сериализаторы в Unity работают в игровой среде в реальном времени. Это оказывает значительное влияние на производительность. Таким образом, сериализация в Unity ведет себя иначе, чем сериализация в других средах программирования. В следующем разделе описывается, как использовать сериализацию в Unity. Чтобы использовать сериализацию полей, вы должны убедиться в этом:
- является
общедоступным
или имеет атрибут SerializeField - Не является
статическим
- Не
const
- Не
только для чтения
- Имеет
тип поля
, который можно сериализовать. (См. раздел Простые типы полей, которые можно сериализовать, ниже.)
Простые типы полей, которые можно сериализовать
- Пользовательские неабстрактные, необобщенные классы с атрибутом
Serializable
(См. раздел Как обеспечить возможность сериализации пользовательского класса ниже.) - Пользовательские структуры с атрибутом
Serializable
- Ссылки на объекты, производные от UnityEngine.Object
- Примитивные типы данных (
int
,float
,double
,bool
,string
и т. д.) - Типы перечислений
- Некоторые встроенные типы Unity:
Vector2
,Vector3
,Vector4
,Rect
,Quaternion
,Matrix4x4
,Color
,Color32
,LayerMask
,AnimationCurve
,Градиент
,RectOffset
,GUIStyle
Типы полей контейнера, которые можно сериализовать
- Массив простого типа поля, который можно сериализовать
Список
простого типа поля, который можно сериализовать
Примечание. Unity не поддерживает сериализацию многоуровневых типов (многомерные массивы, зубчатые массивы и типы вложенных контейнеров). Если вы хотите их сериализовать, у вас есть два варианта: обернуть вложенный тип в класс или структуру или использовать обратные вызовы сериализации ISerializationCallbackReceiver для выполнения пользовательской сериализации. Дополнительные сведения см. в документации по Пользовательской сериализации.
Как убедиться, что пользовательский класс можно сериализовать
Убедитесь:
- Имеет атрибут Serializable
- Не является абстрактным
- Не статично
- Не является универсальным, хотя может наследоваться от универсального класса.
Чтобы обеспечить сериализацию полей пользовательского класса или структуры, см. раздел Как обеспечить сериализацию поля в скрипте выше.
Когда сериализатор может вести себя неожиданно?
Пользовательские классы ведут себя как структуры
С пользовательскими классами, которые не являются производными от UnityEngine.Object, Unity сериализует их по значению, подобно тому, как он сериализует структуры. Если вы храните ссылку на экземпляр пользовательского класса в нескольких разных полях, при сериализации они становятся отдельными объектами. Затем, когда Unity десериализует поля, они содержат разные объекты с идентичными данными.
Если вам нужно сериализовать сложный граф объектов со ссылками, не позволяйте Unity автоматически сериализовать объекты. Вместо этого используйте ISerializationCallbackReceiver
, чтобы сериализовать их вручную. Это не позволяет Unity создавать несколько объектов из ссылок на объекты. Дополнительные сведения см. в документации по ISerializationCallbackReceiver.
Это верно только для пользовательских классов. Unity сериализует пользовательские классы «встроенно», потому что их данные становятся частью полных данных сериализации для MonoBehaviour или ScriptableObject, в которых они используются. Когда поля ссылаются на что-то, что является классом, производным от UnityEngine.Object, например public Camera myCamera
, Unity сериализует реальную ссылку на камерукомпонент, который создает изображение определенной точки обзора в вашей сцене. Вывод либо рисуется на экране, либо фиксируется в виде текстуры. Подробнее
См. в Словарь UnityEngine.Object
. То же самое происходит с экземплярами скриптов, если они являются производными от MonoBehaviour
или ScriptableObject
, которые оба являются производными от UnityEngine.Object
.
Нет поддержки null
для пользовательских классов
Учитывайте, сколько выделений памяти выполняется при десериализации MonoBehaviour
, в котором используется следующий скрипт.
class Test : MonoBehaviour
{
public Trouble t;
}
[Serializable]
class Trouble
{
public Trouble t1;
public Trouble t2;
public Trouble t3;
}
Не странно было бы ожидать одно выделение: объект Test
. Также было бы не странно ожидать два распределения: одно для объекта Test
и одно для объекта Trouble
.
Однако на самом деле Unity производит более тысячи аллокаций. Сериализатор не поддерживает null. Если он сериализует объект, а поле имеет значение null, Unity создает экземпляр нового объекта этого типа и сериализует его. Очевидно, что это может привести к бесконечным циклам, поэтому существует ограничение глубины в семь уровней. В этот момент Unity прекращает сериализацию полей, которые имеют типы пользовательских классов, структур, списков или массивов.
Поскольку многие подсистемы Unity строятся поверх системы сериализации, этот неожиданно большой поток сериализации для Test MonoBehaviour
приводит к тому, что все эти подсистемы работают медленнее, чем необходимо.
Нет поддержки полиморфизма
Если у вас есть общедоступные животные Animal[]
и вы помещаете экземпляр Dog
, Cat
и Giraffe
, после сериализации у вас есть три экземпляра Animal
. р>
Один из способов справиться с этим ограничением – понять, что оно применяется только к пользовательским классам, которые сериализуются в процессе работы. Ссылки на другие UnityEngine.Objects
сериализуются как фактические ссылки, и для них полиморфизм действительно работает. Вы должны создать производный класс ScriptableObject
или другой производный класс MonoBehaviour
и ссылаться на него. Недостатком этого является то, что вам нужно где-то хранить этот Monobehaviour
или объект, доступный для сценария, и что вы не можете эффективно сериализовать его в потоке.
Причина этих ограничений заключается в том, что одной из основных основ системы сериализации является то, что структура потока данных для объекта известна заранее; это зависит от типов полей класса, а не от того, что хранится внутри полей.
Советы
Оптимальное использование сериализации
Вы можете организовать свои данные, чтобы обеспечить оптимальное использование сериализации Unity.
Организуйте свои данные так, чтобы Unity сериализовала наименьший возможный набор данных. Основная цель этого — не сэкономить место на жестком диске вашего компьютера, а убедиться, что вы можете поддерживать обратную совместимость с предыдущими версиями проекта. Обратная совместимость может стать более сложной на более позднем этапе разработки, если вы работаете с большими наборами сериализованных данных.
Упорядочивайте свои данные, чтобы Unity никогда не сериализовала повторяющиеся данные или кэшированные данные. Это вызывает серьезные проблемы с обратной совместимостью: это сопряжено с высоким риском ошибки, поскольку данные слишком легко могут быть рассинхронизированы.
Избегайте вложенных рекурсивных структур, в которых вы ссылаетесь на другие классы. Макет сериализованной структуры всегда должен быть одинаковым; не зависит от данных и зависит только от того, что отображается в сценарии. Единственный способ ссылаться на другие объекты — использовать классы, производные от UnityEngine.Object. Эти классы полностью разделены; они только ссылаются друг на друга и не встраивают содержимое.
Горячая перезагрузка кода редактора
При перезагрузке скриптов Unity сериализует и сохраняет все переменные во всех загруженных скриптах. После перезагрузки скриптов Unity восстанавливает их исходные значения до сериализации.
При перезагрузке скриптов Unity восстанавливает все переменные, в том числе закрытые, которые соответствуют требованиям сериализации, даже если переменная не имеет атрибута SerializeField. В некоторых случаях вам нужно специально запретить восстановление частных переменных: например, если вы хотите, чтобы ссылка была нулевой после перезагрузки из скриптов. В этом случае используйте атрибут NonSerialized.
Unity никогда не восстанавливает статические переменные, поэтому не используйте статические переменные для состояний, которые необходимо сохранить после перезагрузки скрипта.