1.9K Views
October 05, 18
スライド概要
2018/8/22に開催されたCEDEC2018の講演資料です。
講師:山村 達彦(ユニティ・テクノロジーズ・ジャパン合同会社)
リアルタイム3Dコンテンツを制作・運用するための世界的にリードするプラットフォームである「Unity」の日本国内における販売、サポート、コミュニティ活動、研究開発、教育支援を行っています。ゲーム開発者からアーティスト、建築家、自動車デザイナー、映画製作者など、さまざまなクリエイターがUnityを使い想像力を発揮しています。
ココが変わる! Unityの新しいエディターワークフロー 山村 達彦 ユニティ・テクノロジーズ・ジャパ ン
Unityの代表機能
Unityの代表機能 Prefab を始めとしたアセット管理、コンテンツ配信
最初は簡単、ただ規模が大きくなるとしんどくなる
Prefabのおさらい GameObjectのアセット化 (インスタンス) (アセット)
Prefabのおさらい GameObjectのアセット化 Prefabの更新で他の全てのアセットに反映
Prefabのおさらい GameObjectのアセット化 Prefabの更新で他の全てのアセットに反映 値のオーバーライド ATK : 50 DEF : 40 ATK : 100 ATK : 120 DEF : 30 DEF : 30
Prefabのおさらい GameObjectのアセット化 Prefabの更新で他の全てのアセットに反映 値のオーバーライド 参照するアセットの収集
Prefabのおさらい GameObjectのアセット化 Prefabの更新で他の全てのアセットに反映 値のオーバーライド 参照するアセットの収集 何故そんなに一気にしんどく?
編集が面倒くさい 1階層しか表示されない 編集のためには、 編集用シーンを用意する(面倒)
編集が面倒くさい 1階層しか表示されない 特別なスクリプトを作って解決! 編集のためには、 編集用シーンを用意する(面倒)
Prefabを階層化できない GameObject1 Prefab3 Prefab1 Prefab2 元Prefab1 元Prefab2 GameObject1を Prefab化 子PrefabはPrefabではなくなる 大本を更新しても反映されなくなる
Prefabを階層化できない GameObject1 Prefab3 Prefab1 元Prefab1 特別なスクリプトを作って解決! Prefab2 元Prefab2 GameObject1を Prefab化 子PrefabはPrefabではなくなる 大本を更新しても反映されなくなる
Prefab量産後に一括更新が面倒くさい prefab1 prefab2 prefab3 prefab4 prefab5 同じ構成、同じ機能、同じ用途、しかしパラメータが少しずつ違う、別のPrefab 異なるPrefabの為、一括更新が 少々面倒になる
Prefab量産後に一括更新が面倒くさい prefab1 prefab2 prefab3 prefab4 prefab5 特別なスクリプトを作って解決! 同じ構成、同じ機能、同じ用途、しかしパラメータが少しずつ違う、別のPrefab 異なるPrefabの為、一括更新が 少々面倒になる
アセットを直接参照すると、自動的にロードされてしまう Prefab
アセットを直接参照すると、自動的にロードされてしまう Texture Model Prefab Material Audio Prefab Shader Texture
アセットを直接参照すると、自動的にロードされてしまう Texture Model Prefab Material Audio Shader 特別なスクリプトを作って解決! Prefab Texture
AssetBundleに移行すると、確認作業が大変 規模が大きくなると AssetBundleを生成 すごく時間がかかる アセットの調整 動作を確認
AssetBundleに移行すると、確認作業が大変 規模が大きくなると AssetBundleを生成 すごく時間がかかる 特別なスクリプトを作って解決! アセットの調整 動作を確認
AssetBundleの配信が面倒くさい • バージョン、キャッシュ、依存関係、アセット格納先、開放タイミング等、考えることが多い • ローカルのアセットと依存関係を構築できない • ビルドする為にコードが必要
AssetBundleの配信が面倒くさい • バージョン、キャッシュ、依存関係、アセット格納先、開放タイミング等、考えることが多い • ローカルのアセットと依存関係を構築できない 特別な人を作って解決! • ビルドする為にコードが必要
“ 特別なコードが必要なケースが 多すぎる!!! ”
“ もっと開発で 楽したい! ”
New Prefab Workflow Addressable Asset System
柔軟に New Prefab Workflow 複数人で作りやすく 編集結果が一致して 直感的で 使いやすく 効率的で 安全
面倒な追加コード無しに直感的に操作が可能になるということ
新しいPrefabのUI
GameObject Prefab アイコンが追加、視覚的に区別される
変更したパラメータには青い線がつく
Prefabの変更オブジェクト 一覧表示される
変更内容をプレビュー
フィールド毎に個別に反映
Prefabエディターが追加
Prefabエディターが追加
“ DEMO ”
ここが変わった! 一覧表示 プレビュー 個別反映 Prefab エディター どのオブジェクトが変更されたのかを確認する手間が変わる Prefabの更新を最小限に抑えやすい(マージが楽) 編集用シーンを用意しなくても編集が楽に
Prefabの階層化(Nested Prefab) prefab1 prefab2 +
Prefab Prefab Prefab Prefabの階層化(Nested Prefab)
Prefabの階層化(Nested Prefab)
Prefabの更新で 複数の階層がある場合 Prefab Prefab Prefab
どのPrefabを更新するか 指定する
Nested Prefabの階層化 Prefab1 Prefab2 X=1 Y=1 Prefabを階層化しても、Prefabは維持される X=1 Y=1
Nested Prefabの階層化 Prefab1 Prefab2 X=2 Y=1 X=2 Y=1 オリジナルPrefabを変更すれば、使用してるPrefabにも反映される
Nested Prefabの階層化 Prefab1 X=2 Y=1 Prefab2 Prefab3 参照する全てのPrefabが反映してしまう X=2 Y=1 X=2 Y=1
Nested Prefabのオーバーライド Prefab1 Prefab2 X=2 Y=1 X=2 Y=1
Nested Prefabのオーバーライド Prefab1 Prefab2 X=2 Y=1 親のPrefabが子のPrefabの値を上書きする X=2 Y=4
Nested Prefabのオーバーライド Prefab1 X=2 Y=1 Prefab2 Prefab3 他のPrefabには反映されない X=2 Y=4 X=2 Y=1
Nested Prefabのオーバーライド Prefab1 X=2 Y = 12 Prefab2 Prefab3 X=2 Y=4 X=2 Y = 12 オーバーライドした値が優先される点には注意
“ DEMO ”
Prefabのバリアント Variant =本質的には同じものだが、 少しずつ異なるPrefab Prefabを元にPrefabを生成 大体同じだが、 異なる設定を持つPrefab
Prefab1 X=1 Y=1
Prefab1 Prefab2 X=1 X=1 Y=1 Y=1 Variantを作成
Prefab1 Prefab2 X=1 X=2 Y=1 Y=1 個別に値をオーバーライドできる
Prefab1 Prefab2 X=1 X=2 Y=5 Y=5 大本Prefabを更新すると、反映される
“ DEMO ”
モデルの更新 Prefab Prefabを自動生成 Model (FBX) メッシュ ボーン構造 追加した 子オブジェクト コンポーネント
モデルの更新(いままで) 元Prefab メッシュ ボーン構造 追加した Prefab メッシュ ボーン構造 追加した 子オブジェクト 構造が異なると作り直し 子オブジェクト コンポーネント コンポーネント
モデルの更新 元Prefab メッシュ ボーン構造 追加した Prefab メッシュ ボーン構造 追加した 子オブジェクト 子オブジェクト モデルのオブジェクトが独立 コンポーネント オブジェクトを更新すると反映 コンポーネント
ここが変わった! Nested Prefabを細かく分割しやすくなった! Prefab 編集した時の動作 バリアント Prefabの一括更新がやりやすくなった バリエーションを作るときにスクリプトとか無くてもなんとかなる モデルの更新もやりやすくなった
Addressable Asset System 動的なメモリマネジメント 依存関係の制御 ダイナミックなコンテンツの配信 アセットの参照をもっと簡単に 繰り返し確認しやすく
Resources 普通にアセットを参照するのはすごく簡単
アセットを参照すると、自動的にロードされてしまう Texture Model Material Prefab Audio Prefab • とはいえAssetBundleにすると途端に面倒くさい事になる Shader Texture
直接参照か、ResourcesかAssetBundleか • 直接参照 SceneやPrefabからアセットへ直接参照する 関連するアセットが速やかに根こそぎロードされる • Resources 名前ベースで指定したアセットをロードする。(現在非推奨) • AssetBundle アセットを外部ファイルにまとめて配信する バージョン、キャッシュ、依存関係、アセット格納先、開放タイミング等、考えることが多い
直接参照か、ResourcesかAssetBundleか • 直接参照 完全に関係のあるアセット 即座にアセットがロードされる • Addressable Asset System 関係の薄いアセット 格納場所を気にせずアセットをロードできる
直接参照、Resourcesの使いやすさを AssetBundleの環境に提供
導入はPackageManager経由
アセット参照のためのコード [SerializeField] GameObject player;
アセット参照のためのコード [SerializeField] GameObject player; [AssetReferenceTypeRestriction(typeof(GameObject))] public AssetReference player;
アセット参照のためのコード [SerializeField] GameObject player; [AssetReferenceTypeRestriction(typeof(GameObject))] public AssetReference player; 参照する(予定の)アセットのアドレス
アセット参照のためのコード [SerializeField] GameObject player; 参照する(予定の)アセットの型 [AssetReferenceTypeRestriction(typeof(GameObject))] public AssetReference player;
アセット参照のためのコード [AssetReferenceTypeRestriction(typeof(GameObject))] public AssetReference player;
Addressableにオブジェクトを登録
Addressableにオブジェクトを登録
オブジェクトの生成 今まで GameObject playerInstance; playerInstance = Object.Instantiate(player); Addressable GameObject playerInstance; player.Instantiate<GameObject>().Completed += (op) => {playerInstance = op.Result;}
オブジェクトの生成 今まで GameObject playerInstance; playerInstance = Object.Instantiate(player); Addressable 基本的に非同期で動作するAPI GameObject playerInstance; player.Instantiate<GameObject>().Completed += (op) => {playerInstance = op.Result;}
オブジェクトの破棄 今まで Destroy(playerInstance); Resources.UnloadAsset(asset); Addressable Addressables.ReleaseInstance(playerInstance); Addressables.ReleaseAsset(asset);
“ DEMO ”
AssetBundleに登録したアセットの確認
AssetBundleに登録したアセットの確認 AddressableAssetに登録されているアセットの一覧
AssetBundleに登録したアセットの確認 アセットの所属するグループ グループ毎に配信の形態を設定できる (サーバー上に配置、StreamingAssetsに配置等)
AssetBundleに登録したアセットの確認 参照のために使用する名前(アドレス)
AssetBundleに登録したアセットの確認 検索や絞り込みに使用されるラベル (複数登録可)
ラベルに指定したアセットの事前ロード var preloadOp = Addressables.PreloadDependencies("preload", null); yield return preloadOp; “preload”のラベルを持つアセットを 事前にロードしておく
ラベルを指定したアセット一覧を取得 public AssetLabelReference hazardsLabel; var op = Addressables.LoadAssets<IResourceLocation>(hazardsLabel.labelString, null); yield return op; hazardLocations = new List<IResourceLocation>(op.Result);
アドレスから直接オブジェクトを生成する Addressables.Instantiate<GameObject>("Done_Player");
データの格納場所はグループ単位 グループ毎にAssetBundleを 配置するパスを指定 ローカル or サーバー等
プロファイル 接続先を複数用意しておき、 選択一つで切替可能 ステージング用、本番用等
格納方式もグループ単位 pack Separately pack Together 1Addressable 1AssetBundle 1つのAssetBundleに纏める
Addressable Asset Systemは基本的にAssetBundle 規模が大きくなると すごく時間がかかる AssetBundleを生成 アセットの調整 動作を確認
Fastモード、Virtualモード、Packedモード コンテンツを確認する上で 新しいオプションが追加された
Fastモード、Virtualモード、Packedモード Fast: AssetBundleを構築せず、 AssetDatabaseから直接アセットを取得 パフォーマンス的に若干動作が異なる事がある ゲームの動作を確認する上で便利 アセットの調整 動作を確認
Fastモード、Virtualモード、Packedモード Packed: AssetBundleを構築し、AssetBundleから アセットを取得する。 リリース後の動作と同じ。最終動作確認用 AssetBundleを生成 アセットの調整 動作を確認
Fastモード、Virtualモード、Packedモード Virtual: AssetBundleは作成しない コンテンツのレイアウトやアセットの依存関係を 考慮してロードする。 コンテンツの読込状況や分割の戦略を考える用途 ResourceManager更新 アセットの調整 動作を確認
Resource Profiler ( PM Profiler)
Resource Profiler ( PM Profiler)
ここが変わった! Addressable Virtual / Fastモード メモリ管理 AssetBundleへの参照がResourcesや直接参照並みに簡単に AssetBundleビルド待ちせず調整が可能に 検証がやりやすくなった 参照カウンターで自動的に開放される 色々考えなくても良い感じによしなにしてくれるようになった
Addressable、ResourceManagerの拡張 AddressableはC# PackageManagerで提供されている つまり改造できる
“ 今までアセット制御のために 多くのスクリプトを要求していた ”
“ AddressableとNew Prefab Workflowで 特別なコードを書かなくとも 良い感じにアセットを制御しやすくなった ”
“ 今後は、色々面倒なことしなくても、 素直にアセットの作成や量産、読込が可能に! ”
Thank you! ご静聴ありがとうございました