Создание ассетов в AssetBundles
Чтобы построить ассеты в AssetBundle, необходимо назначить ассеты AssetBundleлибо в Unity Editor, либо через скрипт. Затем можно создать и использовать скрипт для построения AssetBundles. Информацию о наилучших методах организации ассетов в AssetBundles см. в Подготовка ассетов для AssetBundles.
Примечание: Этот рабочий процесс описывает создание AssetBundles с помощью встроенного пакета BuildPipeline.BuildAssetBundles API.. Более удобной альтернативой является использование пакета Addressables.
AssetBundle скрипт сборки
Чтобы построить AssetBundles, необходимо создать скрипт сборки и поместить его в папку Editor в папке Assets.
Следующий скрипт является примером скрипта сборки AssetBundle. Он добавляет пункт меню в нижнюю часть меню Ассеты под названием Build AssetBundles. При выборе Build AssetBundles вызывается метод BuildAllAssetBundles. Пока сборка принимает все ассеты, помеченные именем AssetBundle, и использует их для заполнения AssetBundles в пути, определенном assetBundleDirectory, появляется индикатор прогресса.
using UnityEditor;
using System.IO;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
// Ensure the AssetBundles directory exists, and if it doesn't, create it.
string assetBundleDirectory = "Assets/AssetBundles";
if (!Directory.Exists(assetBundleDirectory))
Directory.CreateDirectory(assetBundleDirectory);
// Build all AssetBundles and place them in the specified directory.
BuildPipeline.BuildAssetBundles(assetBundleDirectory,
BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows);
}
}
Скрипт имеет следующие аргументы:
assetBundleDirectory: Каталог для вывода AssetBundles в текущем проекте Unity. Папка не обязательно должна находиться в папкеAssets. В примере кода она создаёт папку по требованию, если она не существует.BuildAssetBundleOptions.None: Значение по умолчанию для аргумента build options. Этот аргумент можно использовать для указания одного или нескольких флагов, чтобы включить различные дополнительные поведения. Например, этот аргумент управляет выбором алгоритм сжатия. Полный перечень имеющихся вариантов см. в 2000 годBuildAssetBundleOptionsAPI документация.BuildTarget.StandaloneWindows: Определяет целевая платформа на 2000 год AssetBundles. Альтернативно, вы можете позвонитьEditorUserBuildSettings.activeBuildTarget, который возвращает профиль платформы, в настоящее время установленный как активный в Создание профилей окно.
Создание подмножеств AssetBundles
Когда вы не даёте методу BuildPipeline.BuildAssetBundles конкретных имен AssetBundle, он строит все AssetBundles, определенные в проекте. Если вы хотите строить только подмножество AssetBundles, вы запрашиваете AssetDatabase для определенного AssetBundles и затем передаете фильтрованный список в конвейер сборки.
Следующий скрипт демонстрирует, как получить все имена AssetBundle и назначенные им ассеты, что позволяет фильтровать или изменять список перед построением:
using UnityEditor;
using System.IO;
using UnityEngine;
using System.Collections.Generic;
public class BuildSubsetAssetBundles
{
[MenuItem("Assets/Build Selected AssetBundles")]
static void BuildSpecificAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles";
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
List<AssetBundleBuild> builds = new List<AssetBundleBuild>();
string[] allAssetBundleNames = AssetDatabase.GetAllAssetBundleNames();
// Example: Only build AssetBundles that start with "environment"
foreach (string bundleName in allAssetBundleNames)
{
if (bundleName.StartsWith("environment"))
{
AssetBundleBuild build = new AssetBundleBuild
{
assetBundleName = bundleName,
assetNames = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName)
};
builds.Add(build);
}
}
if (builds.Count > 0)
{
BuildPipeline.BuildAssetBundles(assetBundleDirectory,
builds.ToArray(),
BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows);
Debug.Log($"Built {builds.Count} specific AssetBundles.");
}
else
{
Debug.Log("No AssetBundles matching criteria found to build.");
}
}
[MenuItem("Assets/Log All AssetBundle Assignments")]
static void LogAllAssetBundleAssignments()
{
string[] allAssetBundleNames = AssetDatabase.GetAllAssetBundleNames();
Debug.Log($"Total AssetBundles Defined: {allAssetBundleNames.Length}");
foreach (string bundleName in allAssetBundleNames)
{
string[] assetPaths = AssetDatabase.GetAssetPathsFromAssetBundle(bundleName);
Debug.Log($"AssetBundle: {bundleName} (Assets: {assetPaths.Length})");
foreach (string path in assetPaths)
{
Debug.Log($" - {path}");
}
}
}
}
Этот подход позволяет вашему скрипту учитывать существующие назначения Inspector, одновременно давая вам гранулярный контроль над тем, как AssetBundles строится.
Выполнить чистую сборку
Когда вы создаете официальный AssetBundle освобождение, выполнение чистая сборка для обеспечения Unity восстанавливает все содержимое во время процесса сборки. Чтобы выполнить чистую сборку, передайте BuildAssetBundleOptions.ForceRebuildAssetBundle флаг в качестве альтернативы BuildPipeline.BuildAssetBundles.
В некоторых проектах можно удалить каталог Library/ShaderCache, чтобы принудить к полной перекомпиляции шейдеров или освободить дисковое пространство от устаревших данных шейдеров. Однако удаление каталога ShaderCache увеличивает время, необходимое Unity для создания новой сборки.
Дополнительные сведения о чистых сборках см. в Создание чистой сборки.
Изменение целевой платформы
BuildPipeline.BuildAssetBundles API позволяет указать целевую и подцелевую платформу для развертывания AssetBundles.
Если указанная целевая платформа отличается от платформы, настроенной в Создание профилей, Unity должен перекомпилировать скрипты редактора и повторно импортировать ассеты, такие как текстуры, которые имеют представления, специфичные для платформы. После завершения сборки Unity восстанавливает исходные настройки целевой платформы.
Этот процесс может значительно увеличить время сборки. Кроме того, скрипт, содержащий вызов BuildPipeline.BuildAssetBundles, продолжает выполняться как скомпилированный для текущей целевой платформы, а не для указанной цели сборки. Это может вызвать проблемы, если скрипт сборки или скрипты обратного вызова опираются на код или сборки для конкретной платформы.
Чтобы избежать этой проблемы, убедитесь, что любой код, выполняемый во время сборки, динамически проверяет целевую платформу (например, с помощью инструкций if), а не полагается на условную компиляцию, специфическую для платформы (например, инструкции #ifdef). Наилучшей практикой является всегда устанавливать цель на желаемую цель, а затем запускать скрипт, который собирает AssetBundles, чтобы избежать любых проблем, связанных с кодом, не поддающимся вашему контролю, таких как обратные вызова сборки внутри пакетов.
Для сборки из командной строки используйте --buildTarget или -activeBuildProfile аргумент командной строки для согласования целевой платформы с требованиями построения. Дополнительные сведения см. в разделе Создание сборки из командной строки.
Постепенное восстановление ассетов
Каждый AssetBundle имеет хэш, который Unity использует для определения необходимости восстановления. Unity определяет, как восстановить AssetBundles постепенно следующим образом:
- Если файл
.manifestиз предыдущей сборки AssetBundle существует, Unity сравнивает хэши IncrementalBuildHash из обеих сборок. - Если хэши AssetBundle совпадают, то Unity вычисляет и сравнивает их хэши дерева типов. Unity использует
TypeTreeHashв качестве вторичного хэша для определения того, имеют ли объекты, используемые в AssetBundle, более новые форматы сериализации. Вы можете проигнорировать эту проверку, указав флагBuildAssetBundleOptions.IgnoreTypeTreeChanges. - Если хэш AssetBundle и хэш дерева типов не совпадают, то Unity перестроит AssetBundle, если только вы не указали
BuildAssetBundleOptions.ForceRebuildAssetBundle,, который перестроит AssetBundle каждый раз. - Unity сериализирует вновь рассчитанные значения хеш-функции в файл
.manifestнового AssetBundle.
IncrementalBuildHash для AssetBundle учитывает целевую платформу, включённые ассеты, зависимости, параметры сборки и настройки конкретной платформы — например, усечение мешей и конфигурацию освещения. Однако этот хеш учитывает не все возможные факторы, влияющие на сборку, из-за чего система инкрементальной сборки может не заметить какие-то изменения, а это способно привести к сбоям или неожиданным ошибкам. Используйте инкрементальные сборки для внутренней разработки, но выполняйте чистая сборка при создании сборки выпуска.
Предупреждение: TypeTreeHash отличается от основного AssetBundle входной хэш (IncrementalBuildHashИзменение в структуре TypeTreeHash может навязать постепенную сборку без изменения AssetBundle входное хэш-значение, так что AssetBundle вводный хэш не является идеальным значением для отслеживания версий файла. Более надежно использовать хэш, основанный на содержании или другой схеме нумерации версий. Для получения дополнительной информации, см. Хеш версии кэша.