Управление ассетами
Управление ассетами с прямой ссылкой является способом управления ассетами по умолчанию во время выполнения в Unity. Каждый раз, когда вы перетаскиваете ассет в сцену или на компонент через окно Inspector Unity Editor, вы создаете прямую ссылку на этот ассет. При создании приложения Unity сохраняет любые ассеты со ссылкой в отдельный файл, связанный со сценами в вашем проекте.
Вы можете использовать прямые ссылки с экземплярами ScriptableObject для эффективного управления большими наборами ассетов и уменьшения размеров сборок. Преимущество использования только прямых ссылок заключается в том, что Unity включает только ассеты, на которые ваш проект напрямую ссылается в сборке, так что ваше приложение не загружает ненужные или дублирующие ассеты.
Прямые ссылки имеют некоторые ограничения, а именно:
- Когда ваше приложение запускается на целевом устройстве, Unity загружает весь файл asset в память перед загрузкой сцены. Этот подход не является динамическим, и вы можете загружать или выгрузить только сцену, что может привести к медленному времени загрузки, особенно на устройствах с меньшей памятью.
- На момент загрузки ресурс должен уже находиться в локальной файловой системе и не может размещаться в сети доставки контента (CDN).
- Нельзя производить постепенные обновления содержимого, и для внесения изменений необходимо перестроить и повторно развернуть все приложение.
Обзор прямой ссылки
В Unity прямая ссылка представляет собой серийную связь от одного объекта к другому. Когда один объект имеет прямую ссылку на другой, он создает зависимость от этого объекта. Когда Unity создает сборку вашего проекта, он следует за всеми прямыми ссылками, чтобы убедиться, что все объекты, которые ссылаются друг на друга, включены в сборку.
В коде C# эти ссылки обычно содержатся объектами, полученными из UnityEngine.Object, такими как GameObject, Materialили MonoBehaviour.
Например, GameObject напрямую ссылается на каждый Component, прикрепленный к нему, например, Transform, MeshRendererили MonoBehaviour скрипт, а Component содержит прямую ссылку на родительский GameObject.
Вы также можете использовать [SerializeReference] для создания ссылок на объекты C#, не производные отUnityEngine.Object.
Unity обрабатывает ссылки на объекты по-разному в зависимости от того, является ли объект, на который делается ссылка, производным от UnityEngine.Objectили объектом C#, на который делается ссылка с помощью [SerializeReference].
Unity ссылки на объекты
Если поле ссылается на объект, полученный из UnityEngine.Object, то Unity не сериализирует все данные объекта, а вместо этого сериализирует указатель на этот объект.
Указатель содержит следующие сведения:
- Глобальный уникальный идентификатор (GUID): 128-битный (32-символьный шестнадцатеричный) ID, который уникально идентифицирует файл ассета на диске, содержащий цель
UnityEngine.Object. Каждый файл ассета в вашем Unity проекте, такой как.prefab,.mat,.png,.unityфайлы сцен и.csфайлы скриптов, имеет соответствующий файл.meta, который хранит его GUID. -
А fileID: 64-разрядный ID, уникальный для целевого объекта в этом конкретном файле ассета. Например, ассет префаб содержит несколько
GameObjectэкземпляры со своими компонентами. Каждый из этих внутреннихUnityEngine.Objectимеет свой уникальныйfileIDвнутри одного файла префаб.
Внутренне, Unity представляет эти ссылки с типом PPtr<T>. Когда Unity загружает эти объекты в память во время выполнения, он разрешает пару GUID и fileID в InstanceID, который он затем использует для отслеживания живого объекта. InstanceID уникальен для текущей сессии Unity Editor или экземпляра времени выполнения.
Если вы откроете файл сцены (.unity) или файл префаб (.prefab) в текстовом редакторе, вы можете проверить ссылки на производные типы UnityEngine.Object, представленные следующим образом:
# A MonoBehaviour on a GameObject referencing a Prefab asset
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 100100000} # Reference to the GameObject this component is on (internal fileID)
m_Enabled: 1
m_EditorHideFlags: 1
m_Script: {fileID: 11500000, guid: f5ee4a4c1e4c3b448a97448840cdf0f41, type: 3} # Reference to the MonoBehaviour script asset (GUID of script file, fileID 11500000 often for MonoBehaviour)
myTargetPrefab: {fileID: 100100000, guid: 61da4d63ca179b54a97448840cdf0f41, type: 3} # Reference to an external Prefab asset (GUID of Prefab file, fileID 100100000 for the root GameObject within the Prefab)
В этом примере, myTargetPrefab указывает на: * fileID: 100100000: Определенный объект ссылки (вероятно, корень GameObject) в целевом файле префаб. * guid: 61da4d63ca179b54a97448840cdf0f41: GUID файла ассета префаб. * type: 3: Тип ассета. type: 3 обычно означает ассет префаб или скрипт.
C# ссылки на объекты
По умолчанию Unity сериализирует любые объекты, не полученные из UnityEngine.Object по значению. Это означает, что он встраивает все данные объекта непосредственно в сериализированные данные объекта, содержащего ссылку.
Вы можете использовать атрибуты [SerializeReference] для изменения этого поведения и указания Unity хранить ссылки на простые объекты C# по ссылке, а не по значению. Это полезно, если вы хотите разрешить нескольким объектам ссылаться на один и тот же объект C# в сериализированной структуре и избежать дублирования данных.
Вы не можете использовать [SerializeReference] к ссылкеa UnityEngine.Object-производный класс. Дополнительные сведения см. в Правила сериализации.
Отслеживание и картирование объектов
Когда Unity загружает ассеты и сцены в память, она использует внутренние структуры данных, сопоставляющие ссылки с живыми объектами. К таким структурам относятся InstanceID, PPtr, Remapper, и PersistentManager. Для UnityEngine.Object ссылки, Unity отображает сериализированные пары GUID и fileID на живой C++ Object. C++ Object имеет указатель на ассоциированный C# UnityEngine.Object и, наконец, объект C# ссылается обратно на ассоциированный объект C++ через экземпляр ID.
Для объектов [SerializeReference], Unity сопоставляет управляемую ссылку IDs с живыми экземплярами объектов. Подробности см. в ManagedReferenceUtility.GetManagedReferenceIdForObject.
Когда Unity строит или загружает ассеты, он создает граф зависимости, начиная с корневого объекта и рекурсивно пересекая все прямые ссылки. Unity загружает полный граф в память, чтобы корневой объект функционировал правильно.
Прямые ссылки могут повлиять на размер сборки приложения. Если на asset UnityEngine.Object прямо ссылается любой объект в вашем проекте, который входит в сборку, то этот asset (и весь его граф прямых зависимостей, разрешенных через пары GUID и fileID) включается. Это означает, что тщательное управление прямыми ссылками крайне важно для предотвращения неиспользуемых или непреднамеренно включенных asset.
Более подробную информацию о файлах, создаваемых Unity при сборке, см. в Вывод содержимого сборки.
Организация больших наборов ассетов
Если у вас есть большие списки ресурсов, которые вам нужно совместно использовать в нескольких сценах, или обновлять без изменения файлов сцены, вы можете использовать экземпляр ScriptableObject для управления этим. Экземпляр ScriptableObject может содержать прямые ссылки на другие ресурсы, которые действуют как каталог ресурсов ссылок на ресурсы вашего проекта. Экземпляры ScriptableObject являются серийными ресурсами и сохраняются в сеансах редактора и сборках. Вы можете повторно использовать их в нескольких различных экземплярах MonoBehaviour, и они могут помочь уменьшить размер файла сцены. Дополнительную информацию см. в документации ScriptableObject.
Вы также можете использовать AssetDatabase.FindAssets для поиска ассетов и заполнения ScriptableObject данными.