Deep-Dive
Into
Scriptable Build Pipeline
Gotanda.unity #12
May 22, 2019
Haruto Otake a.k.a @Trapezoid
Group Manager
Game Developer Library Group
Common Support Services Dept.
Publishing Management Dept. Game Div.
Game & Entertainment Business Unit.
DeNA Co., Ltd.
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
自己紹介
● 大竹 悠人(Haruto Otake)
● 共通基盤部 ゲームデベロッパーライブラリグループ
● a.k.a @Trapezoid
● 2009/4 ドワンゴ 新卒入社
● 2013/5 DeNA 中途入社
● Unityに関連した技術サポートと様々な内製ライブラリの実装・保守に
従事
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Scriptable Build Pipelineとは
● AssetBundleやPlayerのビルドパイプラインをオーバーホールしたもの
● Addressable Assetsからも使われている低レベルAPI
● Package Manager経由でcom.unity.scriptablebuildpipelineとして提供される
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
OK、わかった
● で、何ができるの?
● ビルドフレームワークとしての説明はあるが、具体的にどのぐらいの表現
力があるビルドパイプラインなのかの説明は殆ど無い
● 今回はAssetBundleのビルドパイプラインとしてのSBPに深く切り込んでみ
る
● 基礎的な説明はUnity山村さんの”はじめてのScriptable Build Pipeline”に任せ
て割愛
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
このLTで伝えたいこと
● ScriptableなビルドパイプラインをSBPで構築する上でのとっかかりを得る
● Scriptable Build PipelineによるAssetBundleビルドの構造
● カスタムする上での勘所
● カスタムの具体例
● 資料は後ほど共有する予定です!
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
SBPによるパイプラインの基礎構造
● BuildTaskRunner
● ビルドタスク実行するクラス
● IBuildTaskのリストとIBuildContextを受け取り、DIしつつ順番に実行
● IBuildTask
● 具体的なビルド処理の単位。RunメソッドがRunnerから実行される
● Runnerに渡されたIBuildContextと値をやりとり出来る(DI)
● ContextUsageは参照としてのIn/Outを示すだけなのに注意
● IContextObject
● BuildTask間で共有される情報(入力/出力/状態)
● IBuildContext
● IContextObjectを収容するDIコンテナ
● IContextObjectを継承したinterfaceごとに1つのIContextObjectを収容可
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
SBPによるAssetBundleパイプラインの構造
● SBPの基礎構造に則って、AssetBundleをビルドするためのContextObjectや
BuildTaskが実装されている
● DefaultBuildTasksがBuildTaskを生成
● ContentPipelineで必要なContextObjectを生成して、DefaultBuildTasksで生
成したBuildTaskと共にBuildTaskRunner渡す
● データをタスクごとに様々な視点で見なければいけない関係上、SBPで扱
われるデータには癖がある
● OOP的にわかりやすいArray of Structsではなく、Struct of Arrayっぽく扱
われる
● ContextにどのTaskで何がやりとりされているのかをを正しく理解すれば、
任意の処理を挟み込んでカスタムする余地は十分ある
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
SBPによるAssetBundleパイプラインのターミノロジ
● Asset
● Assetsディレクトリ以下にあるような、ディスク上のソースファイル
● Object (SubAsset)
● Unityがシリアライズできる単位。インポートされたAssetは、1つ以上
のObjectによって構成される(これを2つ以上用いるのがSubAsset)
● SBP中ではGUIDで区別されることが多い
● Includes
● Assetに含まれるObjectのリスト
● References
● Includes内のObjectが依存するが、Includesに含まれないObject
● File
● SBPによるAssetBundleビルドでの書き出し単位。AssetBundleひとつと
1:1の関係で割り当てられる
● Address
● AssetBundle内に格納されたAssetを区別するstring
Via. https://docs.unity3d.com/Packages/com.unity.scriptablebuildpipeline@1.4/manual/Terminology.html
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
DefaultBuildTask
Setup
• SwitchToBuildPlatform
• RebuildSpriteAtlasCac
he
Player Scripts
• BuildPlayerScripts
• PostScriptsCallback
Dependency
• CalculateSceneDependencyD
ata
• CalculateAssetDependencyDa
ta
• StripUnusedSpriteSources
• CreateBuiltInShadersBundle
• PostDependencyCallback
Packing
• GenerateBundlePacking
• UpdateBundleObjectLayout
• GenerateBundleCommands
• GenerateSubAssetPathMaps
• GenerateBundleMaps
• PostPackingCallback
Writing
• WriteSerializedFiles
• ArchiveAndCompressBundles
• AppendBundleHash
• PostWritingCallback
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
外側からの入力となるContextObject
● IBundleBuildContent
● ビルド対象を定義するContextObject
● どのアセット/シーンをビルド対象とするか
● ビルド対象のアセット/シーンが所属するべきAssetBundleの名前
● IBundleBuildParameters
● ビルド対象プラットフォーム, 成果物の出力先, Cache Serverの接続先な
どなど、外側から与える雑多なパラメータを定義するContextObject
● IBuildCache
● 様々なBuildTaskの処理をキャッシュするContextObject
● 標準の実装ではファイルへのシリアライズ + Unity Cache Server
● IDeterministicIdentifiers
● AssetBundleの決定論性を定義するContextObject
● IProgressTracker
● Taskの進行状況を観測する、LoggerとなるContextObject
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Setup
Setup
• SwitchToBuildPlatform
• RebuildSpriteAtlasCac
he
Player Scripts
• BuildPlayerScripts
• PostScriptsCallback
Dependency
• CalculateSceneDependencyD
ata
• CalculateAssetDependencyDa
ta
• StripUnusedSpriteSources
• CreateBuiltInShadersBundle
• PostDependencyCallback
Packing
• GenerateBundlePacking
• UpdateBundleObjectLayout
• GenerateBundleCommands
• GenerateSubAssetPathMaps
• GenerateBundleMaps
• PostPackingCallback
Writing
• WriteSerializedFiles
• ArchiveAndCompressBundles
• AppendBundleHash
• PostWritingCallback
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Setup Tasks
● SwitchToBuildPlatform
● ビルドターゲットにPlatform設定を切り替え
● RebuildSpriteAtlasCache
● SpriteAtlasのキャッシュをリビルド
● 全てのSpriteAtlasのパッキング
● SpriteAtlasUtility.PackAllAtlassesが呼び出される
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Player Scripts
Setup
• SwitchToBuildPlatform
• RebuildSpriteAtlasCac
he
Player Scripts
• BuildPlayerScripts
• PostScriptsCallback
Dependency
• CalculateSceneDependencyD
ata
• CalculateAssetDependencyDa
ta
• StripUnusedSpriteSources
• CreateBuiltInShadersBundle
• PostDependencyCallback
Packing
• GenerateBundlePacking
• UpdateBundleObjectLayout
• GenerateBundleCommands
• GenerateSubAssetPathMaps
• GenerateBundleMaps
• PostPackingCallback
Writing
• WriteSerializedFiles
• ArchiveAndCompressBundles
• AppendBundleHash
• PostWritingCallback
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Player Scripts Tasks
● BuildPlayerScripts
● ビルドターゲット向けの設定でC#スクリプトをコンパイルする
● PostScriptsCallback
● スクリプトコンパイルの完了のタイミングで任意のコールバックをビ
ルドパイプラインの外側から仕込める
● コールバックでSuccess以外のReturnCodeを返せば、ビルドを中断できる
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
BuildPlayerScripts
● 役割
● AssetBundleビルドに必要な型情報をC#のコンパイルをして生成する
● 入力
● IBundleParameters
● ScriptInfo (TypeDB)がセットされていれば
コンパイルをスキップ
● GetCompilationSettingsからコンパイルに
必要なオプションを取得
● 出力
● IBuildResult
● スクリプトコンパイル結果が格納される
● ScriptResults.typeDB (TypeDB)が実体。
シリアライズが可能
IBundleParameters
BuildPlayerScripts
IBuildResults
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Dependency
Setup
• SwitchToBuildPlatform
• RebuildSpriteAtlasCac
he
Player Scripts
• BuildPlayerScripts
• PostScriptsCallback
Dependency
• CalculateSceneDependencyD
ata
• CalculateAssetDependencyDa
ta
• StripUnusedSpriteSources
• CreateBuiltInShadersBundle
• PostDependencyCallback
Packing
• GenerateBundlePacking
• UpdateBundleObjectLayout
• GenerateBundleCommands
• GenerateSubAssetPathMaps
• GenerateBundleMaps
• PostPackingCallback
Writing
• WriteSerializedFiles
• ArchiveAndCompressBundles
• AppendBundleHash
• PostWritingCallback
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Dependency Tasks
● CalculateSceneDependencyData
● CalculateAssetDependencyData
● Scene/AssetのAsset間の依存関係を計算する
● StripUnusedSpriteSources
● 利用していないSpriteへの参照をStripする
● CreateBuiltInShadersBundle
● Standard Shaderなど、Unityのビルトインシェーダを独立した
AssetBundleに自動的にまとめる下準備
● PostDependencyCallback
● PostScriptsCallbackと同様
● IDependencyDataを始めとした、ここまでの主要なContextを受け取れる
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
CalculateAssetDependencyData
CalculateAsset
DependencyData
IBuildContent
IDependencyData
● 役割
● AssetとAssetの間の依存関係を計算する
● 入力
● IBuildContent
● Assets / Scenesから調査対象のファイル名を受け取る
● IBuildParameters
● 型情報の取得や、キャッシュ利用の有無
● IProgressTracker
● 進行状況を記録するロガー
● IBuildCache
● 依存情報のキャッシュ
● 出力
● IDependencyData
● AssetやObjectの間の依存情報
● 入出力
● IBuildExtendedAssetData
● SubAssetの情報を追記
● IBuildSpriteData
● Spriteのパッキング情報を追記
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
IDependencyData
● DependencyData
● AssetInfo (Dictionary<GUID, AssetLoadInfo>)
● SceneInfo (Dictionary<GUID, SceneDependencyInfo>)
● Asset, Scene毎の依存を含む構成の情報
● AssetUsage (Dictionary<GUID, BuildUsageTagSet>)
● SceneUsage (Dictionary<GUID, BuildUsageTagSet>)
● Asset/Scene毎のビルドに必要なメタ情報セット
● ビルドに必要な値だが、ブラックボックスとして扱うしかない
● AssetLoadInfo
● 1つのAssetあたりのObjectの構成情報
● asset(GUID), address(string)
● includedObjects, referencedObjects(List<ObjectIdentifier)
● Assetが含むObjectのリストと、includedObjectsにあるObjectから参照されるが
Assetには含まれないObjectのリスト
● ObjectIdentifier
● guid(GUID), File ID, Path, FileType
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
CreateBuiltinShaderBundle
● 役割
● ビルド対象の中で利用しているビルトインシェーダーを独立した1つの
AssetBundleに分離させる
● 入力
● コンストラクタ(CreateBuiltinShaderBundle(string bundleName)
● 分離させたAssetBundleのAssetBundle名を指定する
● IDependencyData
● DependencyのTaskで生成された依存情報を用いて、抽出作業を行う
● 出力
● IBundleExplicitObjectLayout
● Objectごとに明示的に所属するべきAssetBundleを差し替える場所を示す
● ExplicitObjectLocation(Dictionary<ObjectIdentifier, string>)
● Objectごとに所属するべきAssetBundle名を指定する
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Packing
Setup
• SwitchToBuildPlatform
• RebuildSpriteAtlasCac
he
Player Scripts
• BuildPlayerScripts
• PostScriptsCallback
Dependency
• CalculateSceneDependencyD
ata
• CalculateAssetDependencyDa
ta
• StripUnusedSpriteSources
• CreateBuiltInShadersBundle
• PostDependencyCallback
Packing
• GenerateBundlePacking
• UpdateBundleObjectLayout
• GenerateBundleCommands
• GenerateSubAssetPathMaps
• GenerateBundleMaps
• PostPackingCallback
Writing
• WriteSerializedFiles
• ArchiveAndCompressBundles
• AppendBundleHash
• PostWritingCallback
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Packing
● GenerateBundlePacking
● どのAssetがどのAssetBundleに所属するのかを決定する
● UpdateBundleObjectLayout
● 特定のAssetをAssetBundleに強制的に所属させる
● GenerateBundleCommands
● AssetBundleのSerializeを行うコマンドを生成する
● GenerateSubAssetPathMaps
● SubAssetをコマンドに追加する
● GenerateBundleMaps
● AssetBundleから参照するObjectの参照情報をコマンドに追加する
● PostPackingCallback
● PostDependencyCallbackと同様
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
GenerateBundlePacking
● 役割
● Assetの依存とビルドパラメータを元に、どのAssetがどのAssetBundleに
属するかのパッキング情報を生成する
● 入力
● IBundleBuildContent
● どのAssetがどのAssetBundleに所属するかを明示的に指定するビルドパラメータ
● IDependencyData
● 参照関係や内包するオブジェクトの選択にAssetの依存関係を参照する
● IDeterministicIdentifiers
● Fileの名前の決定に利用
● 出力
● IBundleWriteData - ビルドコマンド生成に必要なパッキング情報を格納
● FileToBundle (Dictionary<string, string>)
● FileとAssetBundle名のマッピングを表す
● FileToUsageSet (Dictionary<string, BuildUsageTagSet>)
● FileToReferenceMap(Dictionary<string, BuildReferenceMap>)
● AssetToFiles (Dictionary<GUID, List<string>>)
● AssetのFile(AssetBundle)への依存を表す。先頭は所属するFileになる
● FileToObjects (Dictionary<string, List<ObjectIdentifier>)
● Fileごとに含まれるObjectを表す
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
UpdateBundleObjectLayout
● 役割
● ビルドタスク中で挟み込まれた明示的なレイアウト指定を、
GenerateBundlePackingで生成したパッキング情報に適用する
● 入力
● IBundleExplicitObjectLayout
● CreateBuiltinShadersBundleなどを通して生成された、上書きすべきパッキング構
成の情報
● IBundleBuildContent
● IDependencyData
● IDeterministicIdentifiers
● 入出力
● IBundleWriteData
● IBundleExplicitObjectLayoutの指定に基づいて各々のメンバを改変する
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
GenerateBundleCommands
● 役割
● パッキング情報を元にAssetBundleのSerializeを行うコマンドを生成する
● 入力
● IBundleBuildContent
● IDependencyData
● IDeterministicIdentifiers
● 入出力
● IBundleWriteData
● AssetBundleのSerializeを行うコマンドを生成し、ReferenceMapなどと関連付ける
● FileToReferenceMap(Dictionary<string, BuildReferenceMap>)
● Fileに含まれるObjectの情報をBuildReferenceMapに追加する
● WriteOperations (List<IWriteOperation>)
● AssetBundleのSerializeコマンドを追加する
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
GenerateBundleMaps
● 役割
● AssetBundle同士の依存関係をコマンドに設定する
● 入力
● IDependencyData
● BuildUsageTagSetの取得に用いる
● 入出力
● IBundleWriteData
● FileToUsageSet
● AssetごとのBuildUsageTagSetをFileごとに集約して合成した上で設定する
● WriteOperations
● FileToReferenceMap
● それぞれのReferenceMapに、依存先AssetBundleの情報も追加する
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Writing
Setup
• SwitchToBuildPlatform
• RebuildSpriteAtlasCac
he
Player Scripts
• BuildPlayerScripts
• PostScriptsCallback
Dependency
• CalculateSceneDependencyD
ata
• CalculateAssetDependencyDa
ta
• StripUnusedSpriteSources
• CreateBuiltInShadersBundle
• PostDependencyCallback
Packing
• GenerateBundlePacking
• UpdateBundleObjectLayout
• GenerateBundleCommands
• GenerateSubAssetPathMaps
• GenerateBundleMaps
• PostPackingCallback
Writing
• WriteSerializedFiles
• ArchiveAndCompressBundles
• AppendBundleHash
• PostWritingCallback
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Writing
● WriteSerializedFiles
● AssetBundleのSerializeコマンドを実行し、ファイルに書き出す
● ArchiveAndCompressBundles
● SerializeされたAssetBundleをアーカイブし、読み込み可能なAssetBundle
ファイルを生成する
● AppendBundleHash
● 要求された場合、ファイル名にHash名を付与して移動する
● PostWritingCallback
● PostDependencyCallbackと同様
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
WriteSerializedFiles
● 役割
● AssetBundleのSerializeコマンドを実行し、ファイルに書き出す
● 読み込み可能なAssetBundleが吐き出されるのではなく、中間ファイル
● 入力
● IBuildParameters
● コマンド実行に必要なパラメータを取得
● IDependencyData
● コマンド実行に必要なGlobalUsageを取得
● IWriteData
● Serializeコマンドを取得して、キャッシュに結果が存在しなければ実行する
● IProgressTracker
● IBuildCache
● キャッシュからSerializeコマンドの実行結果を取得
● 出力
● IBuildResults
● 実行したコマンド実行結果と、キャッシュから取得した以前のコマンド実行結
果をWriteResultsに追加
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
ArchiveAndCompressBundles
● 役割
● Serializeされた中間ファイルを元に読み込み可能なAssetBundleにアーカ
イブし、ファイルに書き出す
● 入力
● IBuildParameters
● IBundleWriteData
● IBuildCache
● IProgressTracker
● 出力
● IBundleBuildResults
● BundleInfos (Dictionary<string, BundleDetails>)
● AssetBundleごとのアーカイブ結果を追加
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
カスタムの勘所
● 特有のターミノロジをしっかり理解する
● AssetBundle自体やAssetBundleビルドの構造の理解にもつながる
● 既存のTaskの間にカスタムタスクを置いてカスタマイズする
● 既存のタスクの実装をいじるのはアップデートに弱く、リスクが高い
(一度やってみて後悔した)
● できるだけパイプラインの最初に近い側から弄る
● ビルドパイプラインの後のほうが、複雑でコンテキストが深い
● 自力で整合性を取るのが困難になっていく
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
HowTo
● 依存してるアセットの型に応じて何らかのアクションをしたい
● ContentBuildInterface.GetTypeForObjectを用いる
● ObjectIdentifierからそのアセットのSystem.Typeを取得可能
● 特定のアセットを別AssetBundleに切り出したい
● CreateBuiltinShaderBundleの方法論はShader以外にも有効
● 切り出したいアセットを特定して、 IBundleExplicitObjectLayoutに登録
● UpdateBundleObjectLayoutで反映
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
具体的な事例
● link.xmlの生成
● Assetの依存関係グラフの生成とCytoscape.jsを使った可視化
● ビルド途中での循環参照の検出
● スクリプトコンパイルのスキップ
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
link.xmlの生成
● AssetBundleにあるAssetから使っているクラスをPreserveするlink.xmlをビル
ド時に自動的に生成する
● このlink.xmlを含めてPlayerをビルドすれば、AssetBundleから使っている
クラスがStripされてしまう事態を避けられる
● Addressable Assetsが備えている機能
● link.xmlの出力自体はAddressableのLinkXmlGeneratorが参考になる
● 型情報(System.Type)を元にXMLを形成できる
● IBundleBuildResults.WriteResultsから、AssetBundleから参照している型の
System.Typeインスタンスを取得できる
● これをLinkXmlGeneratorに放り込めば、link.xmlの生成が可能になる
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
BuildTaskとしてlink.xmlの生成を実行させる
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
Asset依存関係の抽出
● IDependencyDataはランタイム時のアセット依存関係をまとめて参照でき
る
● アセットの依存関係をグラフ出力するのに最適
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
循環参照の検出
● Packingまで終わればAssetBundleのビルドをしなくても、AssetBundle同士
の依存性は検出できる
● AssetToFilesが使える
● 依存性をDictionaryとして抽出すれば、あとはトポロジカルソートして閉
路検出すれば循環参照をビルド前に安価に検出できる
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
スクリプトコンパイルのスキップ
● IBuildParameterのScriptInfoにTypeDBをセットした状態でビルドを開始する
と、スクリプトコンパイルをスキップしてビルドを高速化できる
● BinaryFormatterを使えばTypeDBはシリアライズできる
● ビルド結果はビルド元のソースはもちろん、BuildTargetGroup, BuildTarget,
ScriptCompilationOptionsの三要素によっても変化する
● リポジトリのリビジョン+上記三要素で固有のファイル名をつけて、
TypeDBをシリアライズし、適宜読み出す & ビルド後に保存するように
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
まとめ
● Scriptable Build Pipelineは癖はあるが、非常に表現力の高い形でアセットビ
ルドをカスタマイズできる
● SBPを完全理解して強いビルドパイプラインを作ろう💪💪💪💪💪
*
Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
THANK YOU FOR LISTENING!

Deep-Dive into Scriptable Build Pipeline

  • 1.
    Deep-Dive Into Scriptable Build Pipeline Gotanda.unity#12 May 22, 2019 Haruto Otake a.k.a @Trapezoid Group Manager Game Developer Library Group Common Support Services Dept. Publishing Management Dept. Game Div. Game & Entertainment Business Unit. DeNA Co., Ltd.
  • 2.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. 自己紹介 ● 大竹 悠人(Haruto Otake) ● 共通基盤部 ゲームデベロッパーライブラリグループ ● a.k.a @Trapezoid ● 2009/4 ドワンゴ 新卒入社 ● 2013/5 DeNA 中途入社 ● Unityに関連した技術サポートと様々な内製ライブラリの実装・保守に 従事
  • 3.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Scriptable Build Pipelineとは ● AssetBundleやPlayerのビルドパイプラインをオーバーホールしたもの ● Addressable Assetsからも使われている低レベルAPI ● Package Manager経由でcom.unity.scriptablebuildpipelineとして提供される
  • 4.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. OK、わかった ● で、何ができるの? ● ビルドフレームワークとしての説明はあるが、具体的にどのぐらいの表現 力があるビルドパイプラインなのかの説明は殆ど無い ● 今回はAssetBundleのビルドパイプラインとしてのSBPに深く切り込んでみ る ● 基礎的な説明はUnity山村さんの”はじめてのScriptable Build Pipeline”に任せ て割愛
  • 5.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. このLTで伝えたいこと ● ScriptableなビルドパイプラインをSBPで構築する上でのとっかかりを得る ● Scriptable Build PipelineによるAssetBundleビルドの構造 ● カスタムする上での勘所 ● カスタムの具体例 ● 資料は後ほど共有する予定です!
  • 6.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. SBPによるパイプラインの基礎構造 ● BuildTaskRunner ● ビルドタスク実行するクラス ● IBuildTaskのリストとIBuildContextを受け取り、DIしつつ順番に実行 ● IBuildTask ● 具体的なビルド処理の単位。RunメソッドがRunnerから実行される ● Runnerに渡されたIBuildContextと値をやりとり出来る(DI) ● ContextUsageは参照としてのIn/Outを示すだけなのに注意 ● IContextObject ● BuildTask間で共有される情報(入力/出力/状態) ● IBuildContext ● IContextObjectを収容するDIコンテナ ● IContextObjectを継承したinterfaceごとに1つのIContextObjectを収容可
  • 7.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. SBPによるAssetBundleパイプラインの構造 ● SBPの基礎構造に則って、AssetBundleをビルドするためのContextObjectや BuildTaskが実装されている ● DefaultBuildTasksがBuildTaskを生成 ● ContentPipelineで必要なContextObjectを生成して、DefaultBuildTasksで生 成したBuildTaskと共にBuildTaskRunner渡す ● データをタスクごとに様々な視点で見なければいけない関係上、SBPで扱 われるデータには癖がある ● OOP的にわかりやすいArray of Structsではなく、Struct of Arrayっぽく扱 われる ● ContextにどのTaskで何がやりとりされているのかをを正しく理解すれば、 任意の処理を挟み込んでカスタムする余地は十分ある
  • 8.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. SBPによるAssetBundleパイプラインのターミノロジ ● Asset ● Assetsディレクトリ以下にあるような、ディスク上のソースファイル ● Object (SubAsset) ● Unityがシリアライズできる単位。インポートされたAssetは、1つ以上 のObjectによって構成される(これを2つ以上用いるのがSubAsset) ● SBP中ではGUIDで区別されることが多い ● Includes ● Assetに含まれるObjectのリスト ● References ● Includes内のObjectが依存するが、Includesに含まれないObject ● File ● SBPによるAssetBundleビルドでの書き出し単位。AssetBundleひとつと 1:1の関係で割り当てられる ● Address ● AssetBundle内に格納されたAssetを区別するstring Via. https://docs.unity3d.com/Packages/com.unity.scriptablebuildpipeline@1.4/manual/Terminology.html
  • 9.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. DefaultBuildTask Setup • SwitchToBuildPlatform • RebuildSpriteAtlasCac he Player Scripts • BuildPlayerScripts • PostScriptsCallback Dependency • CalculateSceneDependencyD ata • CalculateAssetDependencyDa ta • StripUnusedSpriteSources • CreateBuiltInShadersBundle • PostDependencyCallback Packing • GenerateBundlePacking • UpdateBundleObjectLayout • GenerateBundleCommands • GenerateSubAssetPathMaps • GenerateBundleMaps • PostPackingCallback Writing • WriteSerializedFiles • ArchiveAndCompressBundles • AppendBundleHash • PostWritingCallback
  • 10.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. 外側からの入力となるContextObject ● IBundleBuildContent ● ビルド対象を定義するContextObject ● どのアセット/シーンをビルド対象とするか ● ビルド対象のアセット/シーンが所属するべきAssetBundleの名前 ● IBundleBuildParameters ● ビルド対象プラットフォーム, 成果物の出力先, Cache Serverの接続先な どなど、外側から与える雑多なパラメータを定義するContextObject ● IBuildCache ● 様々なBuildTaskの処理をキャッシュするContextObject ● 標準の実装ではファイルへのシリアライズ + Unity Cache Server ● IDeterministicIdentifiers ● AssetBundleの決定論性を定義するContextObject ● IProgressTracker ● Taskの進行状況を観測する、LoggerとなるContextObject
  • 11.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Setup Setup • SwitchToBuildPlatform • RebuildSpriteAtlasCac he Player Scripts • BuildPlayerScripts • PostScriptsCallback Dependency • CalculateSceneDependencyD ata • CalculateAssetDependencyDa ta • StripUnusedSpriteSources • CreateBuiltInShadersBundle • PostDependencyCallback Packing • GenerateBundlePacking • UpdateBundleObjectLayout • GenerateBundleCommands • GenerateSubAssetPathMaps • GenerateBundleMaps • PostPackingCallback Writing • WriteSerializedFiles • ArchiveAndCompressBundles • AppendBundleHash • PostWritingCallback
  • 12.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Setup Tasks ● SwitchToBuildPlatform ● ビルドターゲットにPlatform設定を切り替え ● RebuildSpriteAtlasCache ● SpriteAtlasのキャッシュをリビルド ● 全てのSpriteAtlasのパッキング ● SpriteAtlasUtility.PackAllAtlassesが呼び出される
  • 13.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Player Scripts Setup • SwitchToBuildPlatform • RebuildSpriteAtlasCac he Player Scripts • BuildPlayerScripts • PostScriptsCallback Dependency • CalculateSceneDependencyD ata • CalculateAssetDependencyDa ta • StripUnusedSpriteSources • CreateBuiltInShadersBundle • PostDependencyCallback Packing • GenerateBundlePacking • UpdateBundleObjectLayout • GenerateBundleCommands • GenerateSubAssetPathMaps • GenerateBundleMaps • PostPackingCallback Writing • WriteSerializedFiles • ArchiveAndCompressBundles • AppendBundleHash • PostWritingCallback
  • 14.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Player Scripts Tasks ● BuildPlayerScripts ● ビルドターゲット向けの設定でC#スクリプトをコンパイルする ● PostScriptsCallback ● スクリプトコンパイルの完了のタイミングで任意のコールバックをビ ルドパイプラインの外側から仕込める ● コールバックでSuccess以外のReturnCodeを返せば、ビルドを中断できる
  • 15.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. BuildPlayerScripts ● 役割 ● AssetBundleビルドに必要な型情報をC#のコンパイルをして生成する ● 入力 ● IBundleParameters ● ScriptInfo (TypeDB)がセットされていれば コンパイルをスキップ ● GetCompilationSettingsからコンパイルに 必要なオプションを取得 ● 出力 ● IBuildResult ● スクリプトコンパイル結果が格納される ● ScriptResults.typeDB (TypeDB)が実体。 シリアライズが可能 IBundleParameters BuildPlayerScripts IBuildResults
  • 16.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Dependency Setup • SwitchToBuildPlatform • RebuildSpriteAtlasCac he Player Scripts • BuildPlayerScripts • PostScriptsCallback Dependency • CalculateSceneDependencyD ata • CalculateAssetDependencyDa ta • StripUnusedSpriteSources • CreateBuiltInShadersBundle • PostDependencyCallback Packing • GenerateBundlePacking • UpdateBundleObjectLayout • GenerateBundleCommands • GenerateSubAssetPathMaps • GenerateBundleMaps • PostPackingCallback Writing • WriteSerializedFiles • ArchiveAndCompressBundles • AppendBundleHash • PostWritingCallback
  • 17.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Dependency Tasks ● CalculateSceneDependencyData ● CalculateAssetDependencyData ● Scene/AssetのAsset間の依存関係を計算する ● StripUnusedSpriteSources ● 利用していないSpriteへの参照をStripする ● CreateBuiltInShadersBundle ● Standard Shaderなど、Unityのビルトインシェーダを独立した AssetBundleに自動的にまとめる下準備 ● PostDependencyCallback ● PostScriptsCallbackと同様 ● IDependencyDataを始めとした、ここまでの主要なContextを受け取れる
  • 18.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. CalculateAssetDependencyData CalculateAsset DependencyData IBuildContent IDependencyData ● 役割 ● AssetとAssetの間の依存関係を計算する ● 入力 ● IBuildContent ● Assets / Scenesから調査対象のファイル名を受け取る ● IBuildParameters ● 型情報の取得や、キャッシュ利用の有無 ● IProgressTracker ● 進行状況を記録するロガー ● IBuildCache ● 依存情報のキャッシュ ● 出力 ● IDependencyData ● AssetやObjectの間の依存情報 ● 入出力 ● IBuildExtendedAssetData ● SubAssetの情報を追記 ● IBuildSpriteData ● Spriteのパッキング情報を追記
  • 19.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. IDependencyData ● DependencyData ● AssetInfo (Dictionary<GUID, AssetLoadInfo>) ● SceneInfo (Dictionary<GUID, SceneDependencyInfo>) ● Asset, Scene毎の依存を含む構成の情報 ● AssetUsage (Dictionary<GUID, BuildUsageTagSet>) ● SceneUsage (Dictionary<GUID, BuildUsageTagSet>) ● Asset/Scene毎のビルドに必要なメタ情報セット ● ビルドに必要な値だが、ブラックボックスとして扱うしかない ● AssetLoadInfo ● 1つのAssetあたりのObjectの構成情報 ● asset(GUID), address(string) ● includedObjects, referencedObjects(List<ObjectIdentifier) ● Assetが含むObjectのリストと、includedObjectsにあるObjectから参照されるが Assetには含まれないObjectのリスト ● ObjectIdentifier ● guid(GUID), File ID, Path, FileType
  • 20.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. CreateBuiltinShaderBundle ● 役割 ● ビルド対象の中で利用しているビルトインシェーダーを独立した1つの AssetBundleに分離させる ● 入力 ● コンストラクタ(CreateBuiltinShaderBundle(string bundleName) ● 分離させたAssetBundleのAssetBundle名を指定する ● IDependencyData ● DependencyのTaskで生成された依存情報を用いて、抽出作業を行う ● 出力 ● IBundleExplicitObjectLayout ● Objectごとに明示的に所属するべきAssetBundleを差し替える場所を示す ● ExplicitObjectLocation(Dictionary<ObjectIdentifier, string>) ● Objectごとに所属するべきAssetBundle名を指定する
  • 21.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Packing Setup • SwitchToBuildPlatform • RebuildSpriteAtlasCac he Player Scripts • BuildPlayerScripts • PostScriptsCallback Dependency • CalculateSceneDependencyD ata • CalculateAssetDependencyDa ta • StripUnusedSpriteSources • CreateBuiltInShadersBundle • PostDependencyCallback Packing • GenerateBundlePacking • UpdateBundleObjectLayout • GenerateBundleCommands • GenerateSubAssetPathMaps • GenerateBundleMaps • PostPackingCallback Writing • WriteSerializedFiles • ArchiveAndCompressBundles • AppendBundleHash • PostWritingCallback
  • 22.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Packing ● GenerateBundlePacking ● どのAssetがどのAssetBundleに所属するのかを決定する ● UpdateBundleObjectLayout ● 特定のAssetをAssetBundleに強制的に所属させる ● GenerateBundleCommands ● AssetBundleのSerializeを行うコマンドを生成する ● GenerateSubAssetPathMaps ● SubAssetをコマンドに追加する ● GenerateBundleMaps ● AssetBundleから参照するObjectの参照情報をコマンドに追加する ● PostPackingCallback ● PostDependencyCallbackと同様
  • 23.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. GenerateBundlePacking ● 役割 ● Assetの依存とビルドパラメータを元に、どのAssetがどのAssetBundleに 属するかのパッキング情報を生成する ● 入力 ● IBundleBuildContent ● どのAssetがどのAssetBundleに所属するかを明示的に指定するビルドパラメータ ● IDependencyData ● 参照関係や内包するオブジェクトの選択にAssetの依存関係を参照する ● IDeterministicIdentifiers ● Fileの名前の決定に利用 ● 出力 ● IBundleWriteData - ビルドコマンド生成に必要なパッキング情報を格納 ● FileToBundle (Dictionary<string, string>) ● FileとAssetBundle名のマッピングを表す ● FileToUsageSet (Dictionary<string, BuildUsageTagSet>) ● FileToReferenceMap(Dictionary<string, BuildReferenceMap>) ● AssetToFiles (Dictionary<GUID, List<string>>) ● AssetのFile(AssetBundle)への依存を表す。先頭は所属するFileになる ● FileToObjects (Dictionary<string, List<ObjectIdentifier>) ● Fileごとに含まれるObjectを表す
  • 24.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. UpdateBundleObjectLayout ● 役割 ● ビルドタスク中で挟み込まれた明示的なレイアウト指定を、 GenerateBundlePackingで生成したパッキング情報に適用する ● 入力 ● IBundleExplicitObjectLayout ● CreateBuiltinShadersBundleなどを通して生成された、上書きすべきパッキング構 成の情報 ● IBundleBuildContent ● IDependencyData ● IDeterministicIdentifiers ● 入出力 ● IBundleWriteData ● IBundleExplicitObjectLayoutの指定に基づいて各々のメンバを改変する
  • 25.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. GenerateBundleCommands ● 役割 ● パッキング情報を元にAssetBundleのSerializeを行うコマンドを生成する ● 入力 ● IBundleBuildContent ● IDependencyData ● IDeterministicIdentifiers ● 入出力 ● IBundleWriteData ● AssetBundleのSerializeを行うコマンドを生成し、ReferenceMapなどと関連付ける ● FileToReferenceMap(Dictionary<string, BuildReferenceMap>) ● Fileに含まれるObjectの情報をBuildReferenceMapに追加する ● WriteOperations (List<IWriteOperation>) ● AssetBundleのSerializeコマンドを追加する
  • 26.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. GenerateBundleMaps ● 役割 ● AssetBundle同士の依存関係をコマンドに設定する ● 入力 ● IDependencyData ● BuildUsageTagSetの取得に用いる ● 入出力 ● IBundleWriteData ● FileToUsageSet ● AssetごとのBuildUsageTagSetをFileごとに集約して合成した上で設定する ● WriteOperations ● FileToReferenceMap ● それぞれのReferenceMapに、依存先AssetBundleの情報も追加する
  • 27.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Writing Setup • SwitchToBuildPlatform • RebuildSpriteAtlasCac he Player Scripts • BuildPlayerScripts • PostScriptsCallback Dependency • CalculateSceneDependencyD ata • CalculateAssetDependencyDa ta • StripUnusedSpriteSources • CreateBuiltInShadersBundle • PostDependencyCallback Packing • GenerateBundlePacking • UpdateBundleObjectLayout • GenerateBundleCommands • GenerateSubAssetPathMaps • GenerateBundleMaps • PostPackingCallback Writing • WriteSerializedFiles • ArchiveAndCompressBundles • AppendBundleHash • PostWritingCallback
  • 28.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Writing ● WriteSerializedFiles ● AssetBundleのSerializeコマンドを実行し、ファイルに書き出す ● ArchiveAndCompressBundles ● SerializeされたAssetBundleをアーカイブし、読み込み可能なAssetBundle ファイルを生成する ● AppendBundleHash ● 要求された場合、ファイル名にHash名を付与して移動する ● PostWritingCallback ● PostDependencyCallbackと同様
  • 29.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. WriteSerializedFiles ● 役割 ● AssetBundleのSerializeコマンドを実行し、ファイルに書き出す ● 読み込み可能なAssetBundleが吐き出されるのではなく、中間ファイル ● 入力 ● IBuildParameters ● コマンド実行に必要なパラメータを取得 ● IDependencyData ● コマンド実行に必要なGlobalUsageを取得 ● IWriteData ● Serializeコマンドを取得して、キャッシュに結果が存在しなければ実行する ● IProgressTracker ● IBuildCache ● キャッシュからSerializeコマンドの実行結果を取得 ● 出力 ● IBuildResults ● 実行したコマンド実行結果と、キャッシュから取得した以前のコマンド実行結 果をWriteResultsに追加
  • 30.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. ArchiveAndCompressBundles ● 役割 ● Serializeされた中間ファイルを元に読み込み可能なAssetBundleにアーカ イブし、ファイルに書き出す ● 入力 ● IBuildParameters ● IBundleWriteData ● IBuildCache ● IProgressTracker ● 出力 ● IBundleBuildResults ● BundleInfos (Dictionary<string, BundleDetails>) ● AssetBundleごとのアーカイブ結果を追加
  • 31.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. カスタムの勘所 ● 特有のターミノロジをしっかり理解する ● AssetBundle自体やAssetBundleビルドの構造の理解にもつながる ● 既存のTaskの間にカスタムタスクを置いてカスタマイズする ● 既存のタスクの実装をいじるのはアップデートに弱く、リスクが高い (一度やってみて後悔した) ● できるだけパイプラインの最初に近い側から弄る ● ビルドパイプラインの後のほうが、複雑でコンテキストが深い ● 自力で整合性を取るのが困難になっていく
  • 32.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. HowTo ● 依存してるアセットの型に応じて何らかのアクションをしたい ● ContentBuildInterface.GetTypeForObjectを用いる ● ObjectIdentifierからそのアセットのSystem.Typeを取得可能 ● 特定のアセットを別AssetBundleに切り出したい ● CreateBuiltinShaderBundleの方法論はShader以外にも有効 ● 切り出したいアセットを特定して、 IBundleExplicitObjectLayoutに登録 ● UpdateBundleObjectLayoutで反映
  • 33.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. 具体的な事例 ● link.xmlの生成 ● Assetの依存関係グラフの生成とCytoscape.jsを使った可視化 ● ビルド途中での循環参照の検出 ● スクリプトコンパイルのスキップ
  • 34.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. link.xmlの生成 ● AssetBundleにあるAssetから使っているクラスをPreserveするlink.xmlをビル ド時に自動的に生成する ● このlink.xmlを含めてPlayerをビルドすれば、AssetBundleから使っている クラスがStripされてしまう事態を避けられる ● Addressable Assetsが備えている機能 ● link.xmlの出力自体はAddressableのLinkXmlGeneratorが参考になる ● 型情報(System.Type)を元にXMLを形成できる ● IBundleBuildResults.WriteResultsから、AssetBundleから参照している型の System.Typeインスタンスを取得できる ● これをLinkXmlGeneratorに放り込めば、link.xmlの生成が可能になる
  • 35.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. BuildTaskとしてlink.xmlの生成を実行させる
  • 36.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. Asset依存関係の抽出 ● IDependencyDataはランタイム時のアセット依存関係をまとめて参照でき る ● アセットの依存関係をグラフ出力するのに最適
  • 37.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. 循環参照の検出 ● Packingまで終わればAssetBundleのビルドをしなくても、AssetBundle同士 の依存性は検出できる ● AssetToFilesが使える ● 依存性をDictionaryとして抽出すれば、あとはトポロジカルソートして閉 路検出すれば循環参照をビルド前に安価に検出できる
  • 38.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. スクリプトコンパイルのスキップ ● IBuildParameterのScriptInfoにTypeDBをセットした状態でビルドを開始する と、スクリプトコンパイルをスキップしてビルドを高速化できる ● BinaryFormatterを使えばTypeDBはシリアライズできる ● ビルド結果はビルド元のソースはもちろん、BuildTargetGroup, BuildTarget, ScriptCompilationOptionsの三要素によっても変化する ● リポジトリのリビジョン+上記三要素で固有のファイル名をつけて、 TypeDBをシリアライズし、適宜読み出す & ビルド後に保存するように
  • 39.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. まとめ ● Scriptable Build Pipelineは癖はあるが、非常に表現力の高い形でアセットビ ルドをカスタマイズできる ● SBPを完全理解して強いビルドパイプラインを作ろう💪💪💪💪💪
  • 40.
    * Copyright (C) 2013DeNA Co.,Ltd. All Rights Reserved. THANK YOU FOR LISTENING!