unagirabbit's blog

気づいたことをメモしています

ScriptableBuildPipelineでAssetBundleをビルド

初めてのScriptableBuildPipeline

learning.unity3d.jp

具体的にカスタムビルドパイプラインを作るために必要になる知識と具体的なカスタム例

learning.unity3d.jp

ブラックボックスなAssetBundleのビルドステップをカスタムして、
カスタムしたタスクを差し込んだり不要なステップを無くしたりできます。
スクリプトデバッグが行えるのでカスタムは楽だと思います。

Pipelineは3つのプリセットが用意されていますので、
これを参考にカスタムしていくのが良いでしょう。

  • PlayerScriptsOnly
    スクリプトのビルドのみを行う
  • AssetBundleCompatible
    AssetBundleのビルドを行う
  • AssetBundleBuiltInShaderExtraction
    ビルトインシェーダーの重複を排除したAssetBundleのビルドを行う

ただし現時点ではAssetBundleManifestを出力してくれません。
元はAdressable Assetのためのものですからね。

環境

Unity:2019.3.1f1
Scriptable Build Pipeline:1.5.6

DefaultBuildTasksでプリセットのパイプラインを作成し、
パラメーターを渡すだけでサクッと試せます。

1. Pipelineで実行するタスク(IBuildTask)のリストを作成

プリセットでAssetBundleのビルドに必要なタスクのリストを取得できます。
タスクは自由に追加/削除する事ができ順番に実行されます。

// AssetBundleCompatibleのタスクリストを取得する
var tasks = DefaultBuildTasks.Create(DefaultBuildTasks.Preset.AssetBundleCompatible);

2. タスクに必要なパラメーター(IContextObject)を作成

タスクにはパラメーター(IContextObject)を必要とするものもあります。
何のIContextObjectが必要かはタスクの実装を見るのが早いでしょう。

public class SwitchToBuildPlatform : IBuildTask
{
    // 一部抜粋
    // IBuildParametersの入力が必要
    [InjectContext(ContextUsage.In)]
    IBuildParameters m_Parameters;
}

AssetBundleCompatibleのタスクでは2つだけで良いです。

// [IBundleBuildParameters]
// プラットフォームや成果物の出力先などPipelineで必須となるパラメーター
var buildParams = new BundleBuildParameters(buildTarget, BuildPipeline.GetBuildTargetGroup(buildTarget), Application.streamingAssetsPath);

// [IBundleBuildContent]
// ビルドする[AssetBundleBuild]をセットする
var bundleBuilds = ContentBuildInterface.GenerateAssetBundleBuilds();
var bundleBuildContent = new BundleBuildContent(bundleBuilds);

3. BuildTasksRunnerにタスクとパラメーターを渡して実行

BuildTasksRunnerにタスクのリストとパラメーターを渡します。
パラメーターはBuildContextにセットする必要があります。

var buildContext = new BuildContext();
buildContext.SetContextObject(parameters);
buildContext.SetContextObject(bundleBuildContent);
var buildResult = BuildTasksRunner.Run(tasks, buildContext);

まとめ

「読み方さえ分かっていれば中身は結構シンプル」
具体的なカスタム事例はDeep-Dive into Scriptable Build Pipeline参照です。
とりあえずはスクリプトコンパイルをスキップする所だけ試すでも良いかと。
実際のプロダクションへの導入とPlayerのビルドを試していきたと思います。

using UnityEngine;
using UnityEditor;
using UnityEditor.Build.Content;
using UnityEditor.Build.Pipeline;
using UnityEditor.Build.Pipeline.Interfaces;

public static class BuildScriptablePipelineTest
{
    public static void BundlePipeline()
    {
        var buildTarget = EditorUserBuildSettings.activeBuildTarget;
        // --- 1.Pipelineのタスクリストを作成(IBuildTask) --- //
        // Presetからパイプラインのタスクを作成
        // カスタムしたタスクがあれば追加する
        var tasks = DefaultBuildTasks.Create(DefaultBuildTasks.Preset.AssetBundleCompatible);

        // --- 2.Pipelineの実行に必要なパラメーターを設定する(IContextObject) --- //
        // [IBundleBuildParameters]ビルドに必要な基本的なパラメーターを設定します
        var buildParams = new BundleBuildParameters(buildTarget, BuildPipeline.GetBuildTargetGroup(buildTarget), Application.streamingAssetsPath);
        // // scriptInfo(TypeDB)があるならスクリプトコンパイルをスキップできる!
        // buildParams.ScriptInfo = null;
        // // キャッシュサーバはデフォルトtrueなので必要に応じて変更
        // buildParams.UseCache = true;
        // buildParams.CacheServerPort = 8126;
        // buildParams.CacheServerHost = "ホスト";
        // // 圧縮タイプ
        // buildParams.BundleCompression = UnityEngine.BuildCompression.LZMA;

        // [IBundleBuildContent]ビルドするAssetBundleやSceneを設定します
        // 個別に指定する場合はIEnumerable<AssetBundleBuild>で実装
        var bundleBuilds = ContentBuildInterface.GenerateAssetBundleBuilds();
        var bundleBuildContent = new BundleBuildContent(bundleBuilds);

        // 他に必要な[ContextObject]はContentPipelineが作成してくれる

        // --- 3.Tasksを渡してPipelineを実行する(BuildTasksRunner) --- //
        IBundleBuildResults results;
        var buildResult = ContentPipeline.BuildAssetBundles(buildParams, bundleBuildContent, out results, tasks);
    }
}

資料

Scriptable Build Pipeline / Usage Examples

docs.unity3d.com