Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Deep-Dive into Scriptable Build Pipeline

806 views

Published on

SBPを深掘りして、具体的にカスタムビルドパイプラインを作るために必要になる知識と具体的なカスタム例をお伝えします

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Deep-Dive into Scriptable Build Pipeline

  1. 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. 2. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. 自己紹介 ● 大竹 悠人(Haruto Otake) ● 共通基盤部 ゲームデベロッパーライブラリグループ ● a.k.a @Trapezoid ● 2009/4 ドワンゴ 新卒入社 ● 2013/5 DeNA 中途入社 ● Unityに関連した技術サポートと様々な内製ライブラリの実装・保守に 従事
  3. 3. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. Scriptable Build Pipelineとは ● AssetBundleやPlayerのビルドパイプラインをオーバーホールしたもの ● Addressable Assetsからも使われている低レベルAPI ● Package Manager経由でcom.unity.scriptablebuildpipelineとして提供される
  4. 4. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. OK、わかった ● で、何ができるの? ● ビルドフレームワークとしての説明はあるが、具体的にどのぐらいの表現 力があるビルドパイプラインなのかの説明は殆ど無い ● 今回はAssetBundleのビルドパイプラインとしてのSBPに深く切り込んでみ る ● 基礎的な説明はUnity山村さんの”はじめてのScriptable Build Pipeline”に任せ て割愛
  5. 5. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. このLTで伝えたいこと ● ScriptableなビルドパイプラインをSBPで構築する上でのとっかかりを得る ● Scriptable Build PipelineによるAssetBundleビルドの構造 ● カスタムする上での勘所 ● カスタムの具体例 ● 資料は後ほど共有する予定です!
  6. 6. * 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を収容可
  7. 7. * 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で何がやりとりされているのかをを正しく理解すれば、 任意の処理を挟み込んでカスタムする余地は十分ある
  8. 8. * 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
  9. 9. * 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
  10. 10. * 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
  11. 11. * 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
  12. 12. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. Setup Tasks ● SwitchToBuildPlatform ● ビルドターゲットにPlatform設定を切り替え ● RebuildSpriteAtlasCache ● SpriteAtlasのキャッシュをリビルド ● 全てのSpriteAtlasのパッキング ● SpriteAtlasUtility.PackAllAtlassesが呼び出される
  13. 13. * 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
  14. 14. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. Player Scripts Tasks ● BuildPlayerScripts ● ビルドターゲット向けの設定でC#スクリプトをコンパイルする ● PostScriptsCallback ● スクリプトコンパイルの完了のタイミングで任意のコールバックをビ ルドパイプラインの外側から仕込める ● コールバックでSuccess以外のReturnCodeを返せば、ビルドを中断できる
  15. 15. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. BuildPlayerScripts ● 役割 ● AssetBundleビルドに必要な型情報をC#のコンパイルをして生成する ● 入力 ● IBundleParameters ● ScriptInfo (TypeDB)がセットされていれば コンパイルをスキップ ● GetCompilationSettingsからコンパイルに 必要なオプションを取得 ● 出力 ● IBuildResult ● スクリプトコンパイル結果が格納される ● ScriptResults.typeDB (TypeDB)が実体。 シリアライズが可能 IBundleParameters BuildPlayerScripts IBuildResults
  16. 16. * 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
  17. 17. * 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を受け取れる
  18. 18. * 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のパッキング情報を追記
  19. 19. * 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
  20. 20. * 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名を指定する
  21. 21. * 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
  22. 22. * 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と同様
  23. 23. * 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を表す
  24. 24. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. UpdateBundleObjectLayout ● 役割 ● ビルドタスク中で挟み込まれた明示的なレイアウト指定を、 GenerateBundlePackingで生成したパッキング情報に適用する ● 入力 ● IBundleExplicitObjectLayout ● CreateBuiltinShadersBundleなどを通して生成された、上書きすべきパッキング構 成の情報 ● IBundleBuildContent ● IDependencyData ● IDeterministicIdentifiers ● 入出力 ● IBundleWriteData ● IBundleExplicitObjectLayoutの指定に基づいて各々のメンバを改変する
  25. 25. * 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コマンドを追加する
  26. 26. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. GenerateBundleMaps ● 役割 ● AssetBundle同士の依存関係をコマンドに設定する ● 入力 ● IDependencyData ● BuildUsageTagSetの取得に用いる ● 入出力 ● IBundleWriteData ● FileToUsageSet ● AssetごとのBuildUsageTagSetをFileごとに集約して合成した上で設定する ● WriteOperations ● FileToReferenceMap ● それぞれのReferenceMapに、依存先AssetBundleの情報も追加する
  27. 27. * 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
  28. 28. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. Writing ● WriteSerializedFiles ● AssetBundleのSerializeコマンドを実行し、ファイルに書き出す ● ArchiveAndCompressBundles ● SerializeされたAssetBundleをアーカイブし、読み込み可能なAssetBundle ファイルを生成する ● AppendBundleHash ● 要求された場合、ファイル名にHash名を付与して移動する ● PostWritingCallback ● PostDependencyCallbackと同様
  29. 29. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. WriteSerializedFiles ● 役割 ● AssetBundleのSerializeコマンドを実行し、ファイルに書き出す ● 読み込み可能なAssetBundleが吐き出されるのではなく、中間ファイル ● 入力 ● IBuildParameters ● コマンド実行に必要なパラメータを取得 ● IDependencyData ● コマンド実行に必要なGlobalUsageを取得 ● IWriteData ● Serializeコマンドを取得して、キャッシュに結果が存在しなければ実行する ● IProgressTracker ● IBuildCache ● キャッシュからSerializeコマンドの実行結果を取得 ● 出力 ● IBuildResults ● 実行したコマンド実行結果と、キャッシュから取得した以前のコマンド実行結 果をWriteResultsに追加
  30. 30. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. ArchiveAndCompressBundles ● 役割 ● Serializeされた中間ファイルを元に読み込み可能なAssetBundleにアーカ イブし、ファイルに書き出す ● 入力 ● IBuildParameters ● IBundleWriteData ● IBuildCache ● IProgressTracker ● 出力 ● IBundleBuildResults ● BundleInfos (Dictionary<string, BundleDetails>) ● AssetBundleごとのアーカイブ結果を追加
  31. 31. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. カスタムの勘所 ● 特有のターミノロジをしっかり理解する ● AssetBundle自体やAssetBundleビルドの構造の理解にもつながる ● 既存のTaskの間にカスタムタスクを置いてカスタマイズする ● 既存のタスクの実装をいじるのはアップデートに弱く、リスクが高い (一度やってみて後悔した) ● できるだけパイプラインの最初に近い側から弄る ● ビルドパイプラインの後のほうが、複雑でコンテキストが深い ● 自力で整合性を取るのが困難になっていく
  32. 32. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. HowTo ● 依存してるアセットの型に応じて何らかのアクションをしたい ● ContentBuildInterface.GetTypeForObjectを用いる ● ObjectIdentifierからそのアセットのSystem.Typeを取得可能 ● 特定のアセットを別AssetBundleに切り出したい ● CreateBuiltinShaderBundleの方法論はShader以外にも有効 ● 切り出したいアセットを特定して、 IBundleExplicitObjectLayoutに登録 ● UpdateBundleObjectLayoutで反映
  33. 33. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. 具体的な事例 ● link.xmlの生成 ● Assetの依存関係グラフの生成とCytoscape.jsを使った可視化 ● ビルド途中での循環参照の検出 ● スクリプトコンパイルのスキップ
  34. 34. * 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の生成が可能になる
  35. 35. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. BuildTaskとしてlink.xmlの生成を実行させる
  36. 36. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. Asset依存関係の抽出 ● IDependencyDataはランタイム時のアセット依存関係をまとめて参照でき る ● アセットの依存関係をグラフ出力するのに最適
  37. 37. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. 循環参照の検出 ● Packingまで終わればAssetBundleのビルドをしなくても、AssetBundle同士 の依存性は検出できる ● AssetToFilesが使える ● 依存性をDictionaryとして抽出すれば、あとはトポロジカルソートして閉 路検出すれば循環参照をビルド前に安価に検出できる
  38. 38. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. スクリプトコンパイルのスキップ ● IBuildParameterのScriptInfoにTypeDBをセットした状態でビルドを開始する と、スクリプトコンパイルをスキップしてビルドを高速化できる ● BinaryFormatterを使えばTypeDBはシリアライズできる ● ビルド結果はビルド元のソースはもちろん、BuildTargetGroup, BuildTarget, ScriptCompilationOptionsの三要素によっても変化する ● リポジトリのリビジョン+上記三要素で固有のファイル名をつけて、 TypeDBをシリアライズし、適宜読み出す & ビルド後に保存するように
  39. 39. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. まとめ ● Scriptable Build Pipelineは癖はあるが、非常に表現力の高い形でアセットビ ルドをカスタマイズできる ● SBPを完全理解して強いビルドパイプラインを作ろう💪💪💪💪💪
  40. 40. * Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved. THANK YOU FOR LISTENING!

×