Unity 6.3
0 онлайн 78 гостей 3 в системе
Вход
Программирование в Unity Шаг 95 из 210

Как Unity использует сериализацию

Сохранение и загрузка

Unity использует сериализацию для загрузки и сохранения сцены, Активы, и AssetBundles в память вашего устройства и из нее. Это включает данные, сохраненные в вашем собственном сценарии API объекты, такие как MonoBehaviour компоненты и ScriptableObjects.

Многие функции Unity Editor построены на основе основной системы серийного кодирования. Две вещи, которые следует особо учитывать при серийном кодировании, это окно Inspectorи перезагрузка в горячем режиме.

Окно Inspector

Окно Inspector показывает значение серийных полей проверяемых объектов. Когда вы изменяете значение в Inspector, Inspector обновляет серийные данные и вызывает десерриализацию, которая обновляет проверяемый объект.

То же самое относится как к встроенным объектам Unity, так и к объектам скриптов, таким как классы, производные от MonoBehaviour.

Unity не вызывает никаких C# геттеров и сеттеров свойств, когда вы просматриваете или изменяете значения в окне Inspector. Вместо этого Unity напрямую получает доступ к серийному базовому полю.

Горячая перезагрузка

Горячая перезагрузка скриптового кода выполняется как часть обновления базы данных ассетов. Она относится к процессу перезагрузки и применения изменений в коде непосредственно во время работы Редактора, без необходимости его перезапуска. Дополнительные сведения см. в Обновление базы данных активов и Горячая перезагрузка.

Примечание: горячая перезагрузка — особый случай сериализации. В отличие от остальных случаев, при перезагрузке Unity по умолчанию сериализует и закрытые поля, даже если у них нет [SerializeField] атрибут.

Когда Unity перезагружает скрипты:

  1. Unity сериализирует и хранит все переменные во всех загруженных скриптах.
  2. Unity восстанавливает их в исходные значения до сериализации:
    • Unity восстанавливает все переменные включая приватные переменные - которые отвечают требованиям для сериализации, даже если переменная не имеет [SerializeField] атрибут.
    • Unity никогда не восстанавливает статические переменные, поэтому не используйте их для состояний, которые должны пережить перезагрузку скрипта: при перезагрузке они будут отброшены.

Предотвращение серийного номера и восстановления

Иногда нужно помешать Unity восстанавливать закрытые переменные — например, если после перезагрузки скриптов ссылка должна быть равна null. В этом случае используйте [NonSerialized] атрибут.

Поведение восстановления в Unity распространяется и на закрытые поля-хранилища, в которых хранится значение автоматически реализованные свойства в C#. Например, рассмотрим следующее автоматически реализованное свойство:

public string MyProperty { get; set; }

В этом случае C# добавляет в класс невидимое закрытое поле для хранения фактического значения MyProperty. Unity будет сериализировать и восстанавливать это значение во время горячей перезагрузки. [field: NonSerialized] на свойство.

В следующем примере показано использование атрибутов [NonSerialized] и [field: NonSerialized] для предотвращения сериализации и восстановления регулярных полей и подкрепляющего поля соответственно:

class Test
{
    // p will not be shown in the Inspector or serialized
    [System.NonSerialized]
    public int p = 5;

    // neverSerializeMe will never be serialized, even during an hot reload.
    [System.NonSerialized]
    private int neverSerializeMe;

    // The backing field for NeverSerializedProperty property will never be serialized,
    // even during a hot reload
    [field: System.NonSerialized]
    public int NeverSerializedProperty { get; set; }
}

Префабы

Префаб представляет собой сериализованные данные одного или нескольких GameObject или компонентов. Экземпляр префаба содержит ссылку на исходный префаб и список внесённых изменений. Эти изменения указывают Unity, как получить конкретный экземпляр префаба из исходного префаба.

Экземпляр префаб существует только во время редактирования проекта в Unity Editor. Unity Editor инстанционирует GameObject из двух наборов данных сериализации: источник префаб и модификации экземпляра префаб.

Инстанционирование

Когда вы вызываете Instantiate на что-либо, что существует в сцене, например, префаб или GameObject:

  1. Unity сериализирует его. Это происходит как во время выполнения, так и в Редакторе. Unity может сериализировать все, что происходит от UnityEngine.Object.
  2. Unity создает новый GameObject и десериализует данные в новом GameObject.
  3. Unity запускает тот же код серийного номера в другом варианте, чтобы сообщить, какие другие UnityEngine.Objects Он проверяет все ссылки UnityEngine.Objects чтобы определить, входят ли они в данные, которые Unity создаёт заново. Если ссылка указывает на что-то внешнее, например на текстуру, Unity оставляет её как есть. Если ссылка указывает на что-то внутреннее, например на дочерний GameObject, Unity перенаправляет её на соответствующую копию.

Выгрузка неиспользуемого имущества

EditorUtility.UnloadUnusedAssetsImmediate является собственным сборщиком мусора Unity и имеет другое назначение, чем стандартный сборщик мусора C#. Он запускается после загрузки сцены и проверяет объекты (такие как Тексты), на которые она больше не ссылается, и безопасно выгружает их. Собственный сборщик мусора Unity запускает сериализатор в варианте, в котором объекты сообщают все ссылки на внешний UnityEngine.Objects. Таким образом Тексты, используемые одной сценой, сборщик мусора выгружает в следующей.

Различия между редактором и сериализацией времени выполнения

Большая часть сериализации происходит в Редакторе, в то время как десериялизация является фокусом во время выполнения. Unity сериализует некоторые функции только в Редакторе, в то время как она может сериализировать другие функции как в Редакторе, так и во время выполнения:

Особенности Редактор Среда выполнения
Активы в двоичном формате Поддержка чтения/записи Читать поддерживается
Активы в YAML формат Поддержка чтения/записи Не поддерживается
Сохранение сцен, префабы и других активов Поддерживается, если не в режиме воспроизведения Не поддерживается
Сериализация отдельных объектов с JsonUtility Поддержка чтения/записи с JsonUtility.

Поддержка дополнительных типов объектов с EditorJsonUtility
Поддержка чтения/записи с JsonUtility
SerializeReference Поддерживаемые Поддерживаемые
ISerializationCallbackReceiver Поддерживаемые Поддерживаемые
FormerlySerializedAs Поддерживаемые Не поддерживается

Объекты могут иметь дополнительные поля, которые сериализирует только Редактор, например, когда вы декларируете поля в UNITY_EDITOR символ сценария:

public class SerializeRules : MonoBehaviour
{
#if UNITY_EDITOR
public int m_intEditorOnly;
#endif
}

В предыдущем примере, m_intEditorOnly поле сериализируется только в редакторе и не включается в сборку. Это позволяет сэкономить память, пропуская данные, которые требуются только в редакторе из вашей сборки. Любой код, использующий это поле, также должен быть условно компилирован, например, в #if UNITY_EDITOR блоки, чтобы класс компилировался во время сборки.

Редактор не поддерживает объекты с полями, которые Unity сериализирует только во время выполнения (например, когда вы объявляете поля в директиве UNITY_STANDALONE).

Дополнительные ресурсы