Демонстрация работы с Asset Bundle в Unity3D
В этом проекте:
- AssemblyVS - сборка исходного кода в library-файлы
- ClearUnity - проект в Unity, демонстрирующий мощь assetBundle'ов (без прочих зависимостей вида префабов или скриптов)
- ProjectUnity - основной проект, в котором создаются assetBundle
Есть два варианта:
- Сборка через Visual Studio/Mono/etc (использовано в этом проекте);
- Сборка через консоль
- Создать новый проект
Class Library
(можно использовать текущий -Move
); - Реализовать необходимый код;
- Правой кнопкой на
Solution
->Build Solution
; - Любимым файлововым менеджером открываем этот проект;
- Переходим в папку
Debug
(<путь к проекту>
->bin
->Debug
); - У собранного library-файла меняем расширение на
.bytes
(т.к. в assetBunlde нельзя положить.dll
, но двочиные данные можно); - Profit Теперь этот файл можно добавлять в bundle
Процесс ничем не отличается от обычной сборки через консоль:
- Открываем консоль;
- Указываем путь до компилятора
csc.exe
(обычно лежит в../Windows/Microsoft.NET/Framework/<версия>/
); - Указываем пути до зависимых библиотек (например, если используется
UnityEngine.dll
, пишем/r:<путь до Unity3D>/Editor/Data/Managed/UnityEngine.dll
, где/r
- ключ reference, подробности в документации); - Указываем, во что собирать. В данном случае
/target:library
; - И путь до файла(ов), которые хотим собрать;
- Также используйте ключ
-nologo
, чтобы скрыть отображение логотипа и предупреждений. - Profit Теперь этот файл можно добавлять в bundle
О том, как указать в редакторе, какие объекты следует поместить в Asset Bundle читайте в документации
В ProjectUnity
из префабов собраны две сцены. В каждой из них используются одноименные файлы:
- префаб
Scene
- площадка, на которой перемещается Player; - префаб
Player
- объект, который перемещается в соответствии с правилами, описанными в скрпите; - а также скрипт
Move.bytes
(бывшийMove.dll
, см. пункт №1), который в зависимости от положения Player'а решает, куда переместить его дальше.
Название файлов важно, так как только по ним можно будет достать сами объекты из Asset Bundle. Поэтому, для каждой сцены используются одноименные файлы, но с разными тегами (scene1
для всех объектов первой сцены и scene2
- для второй).
Когда все файлы для Asset Bundle отмечены, нужно их собрать: в меню редактора Assets -> Build AssetBundles
(начинает работать скрипт BuildBundler.cs
). Все собранные bundle расположены в ProjectUnity/Assets/AssetBundles
. Ключевыми являются файлы без раширения (или с расширением, так как в качестве тега-названия для Asset Bundle могут быть названия, содержащие точки).
ВАЖНО: чтобы работать с локальными Asset Bundle, необходимо указывать до них путь в виде:
file://localhost/<drive>|/<path>
file:///<drive>|/<path>
file://localhost/<drive>:/<path>
file:///<drive>:/<path>
О загрузке и работе с bundle можно найти здесь
Но этого достаточно только для работы с префабами, чтобы использовать вложенные файлы с кодом, нужно просто использовать рефлексию, как будто бы и нет никакого bundle.
Вот пример загрузки класса, с помощью которого будем передвигать Player
private void LoadScriptMovePlayer()
{
var scriptContent = _bundle.LoadAsset(MoveClassName) as TextAsset;
if (scriptContent == null)
{
Debug.Log("ScriptContent was NULL");
return;
}
var assembly = Assembly.Load(scriptContent.bytes);
var type = assembly.GetType(MoveClassName);
_moveClass = assembly.CreateInstance(MoveClassName);
_moveMethod = type.GetMethod(MoveMethodName);
}
И чтобы вызвать метод этого класса поможет метод Invoke
:
ссылка
WebGL и Asset Bundle дружат очень хорошо. Но для этого, при сборке необходимо об этом указать третьим параметром в BuildBundler.cs
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
BuildPipeline.BuildAssetBundles(
UnityConstants.PathToAssetBundles,
BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows);
}
Так, для Windows это будет BuildTarget.StandaloneWindows
, для WebGL - BuildTarget.WebGL
НО файлы .bytes
не будут работать (никакого исполняемого кода в вебе), так как
No, there is no way around this restriction with reflection. The key difference between the web player and WebGL build targets in Unity in this case is that WebGL uses AOT (ahead-of-time) compilation, whereas the web player uses JIT (just-in-time) compilation. With AOT compilation, it is not possible to load an assembly at run-time that was not present at compile time. Of course, it is possible to load JavaScript code at runtime, so as you suggest, you'll probably need to go this route.
:(