ココが変わる!

Unityの新しいエディターワークフロー
ユニティ・テクノロジーズ・ジャパン
山村 達彦
Unityの代表機能
Unityの代表機能
Prefab
を始めとしたアセット管理、コンテンツ配信
最初は簡単、ただ規模が大きくなるとしんどくなる
GameObjectのアセット化
Prefabのおさらい
(アセット)(インスタンス)
GameObjectのアセット化
Prefabの更新で他の全てのアセットに反映
Prefabのおさらい
GameObjectのアセット化
値のオーバーライド
Prefabの更新で他の全てのアセットに反映
Prefabのおさらい
ATK : 100
DEF : 30
ATK : 120
DEF : 30
ATK : 50
DEF : 40
GameObjectのアセット化
値のオーバーライド
参照するアセットの収集
Prefabの更新で他の全てのアセットに反映
Prefabのおさらい
GameObjectのアセット化
値のオーバーライド
参照するアセットの収集
何故そんなに一気にしんどく?
Prefabの更新で他の全てのアセットに反映
Prefabのおさらい
編集が面倒くさい
1階層しか表示されない
編集のためには、
編集用シーンを用意する(面倒)
編集が面倒くさい
1階層しか表示されない
編集のためには、
編集用シーンを用意する(面倒)
特別なスクリプトを作って解決!
Prefabを階層化できない
GameObject1
Prefab1
Prefab2
Prefab3
元Prefab1
元Prefab2
GameObject1を

Prefab化
子PrefabはPrefabではなくなる
大本を更新しても反映されなくなる
Prefabを階層化できない
GameObject1
Prefab1
Prefab2
Prefab3
元Prefab1
元Prefab2
GameObject1を

Prefab化
子PrefabはPrefabではなくなる
大本を更新しても反映されなくなる
特別なスクリプトを作って解決!
Prefab量産後に一括更新が面倒くさい
同じ構成、同じ機能、同じ用途、しかしパラメータが少しずつ違う、別のPrefab
prefab1 prefab2 prefab3 prefab4 prefab5
異なるPrefabの為、一括更新が
少々面倒になる
Prefab量産後に一括更新が面倒くさい
同じ構成、同じ機能、同じ用途、しかしパラメータが少しずつ違う、別のPrefab
prefab1 prefab2 prefab3 prefab4 prefab5
異なるPrefabの為、一括更新が
少々面倒になる
特別なスクリプトを作って解決!
アセットを直接参照すると、自動的にロードされてしまう
Prefab
アセットを直接参照すると、自動的にロードされてしまう
Prefab
Texture
Model
Material
Prefab Texture
Audio Shader
アセットを直接参照すると、自動的にロードされてしまう
Prefab
Texture
Model
Material
Prefab Texture
Audio Shader
特別なスクリプトを作って解決!
規模が大きくなると
すごく時間がかかる
動作を確認アセットの調整
AssetBundleを生成
AssetBundleに移行すると、確認作業が大変
規模が大きくなると
すごく時間がかかる
動作を確認アセットの調整
AssetBundleを生成
AssetBundleに移行すると、確認作業が大変
特別なスクリプトを作って解決!
• バージョン、キャッシュ、依存関係、アセット格納先、開放タイミング等、考えることが多い
• ローカルのアセットと依存関係を構築できない
• ビルドする為にコードが必要
AssetBundleの配信が面倒くさい
• バージョン、キャッシュ、依存関係、アセット格納先、開放タイミング等、考えることが多い
• ローカルのアセットと依存関係を構築できない
• ビルドする為にコードが必要
AssetBundleの配信が面倒くさい
特別な人を作って解決!
“ ”
特別なコードが必要なケースが
多すぎる!!!
“ ”
もっと開発で

楽したい!
New Prefab Workflow
Addressable Asset System
New Prefab 

Workflow
柔軟に

複数人で作りやすく
編集結果が一致して

直感的で
使いやすく
効率的で
安全
面倒な追加コード無しに直感的に操作が可能になるということ
新しいPrefabのUI
アイコンが追加、視覚的に区別される
Prefab
GameObject
変更したパラメータには青い線がつく
Prefabの変更オブジェクト

一覧表示される
変更内容をプレビュー
フィールド毎に個別に反映
Prefabエディターが追加
Prefabエディターが追加
“ ”
DEMO
ここが変わった!
どのオブジェクトが変更されたのかを確認する手間が変わる
一覧表示
プレビュー
個別反映 Prefabの更新を最小限に抑えやすい(マージが楽)
Prefab

エディター
編集用シーンを用意しなくても編集が楽に
Prefabの階層化(Nested Prefab)
+
prefab1 prefab2
Prefabの階層化(Nested Prefab)
Prefab
Prefab
Prefab
Prefabの階層化(Nested Prefab)
Prefabの更新で
複数の階層がある場合
Prefab
Prefab
Prefab
どのPrefabを更新するか
指定する
Nested Prefabの階層化
X = 1
Prefab1
X = 1Y = 1
Y = 1
Prefab2
Prefabを階層化しても、Prefabは維持される
Nested Prefabの階層化
X = 2
Prefab1
X = 2Y = 1
Y = 1
Prefab2
オリジナルPrefabを変更すれば、使用してるPrefabにも反映される
Nested Prefabの階層化
X = 2
Prefab1 X = 2
Y = 1
Y = 1
Prefab2
参照する全てのPrefabが反映してしまう
X = 2
Y = 1
Prefab3
Nested Prefabのオーバーライド
X = 2
Prefab1
X = 2Y = 1
Prefab2
Y = 1
Nested Prefabのオーバーライド
X = 2
Prefab1
X = 2Y = 1
Prefab2
親のPrefabが子のPrefabの値を上書きする
Y = 4
Nested Prefabのオーバーライド
X = 2
Prefab1 X = 2
Y = 1
Prefab2
他のPrefabには反映されない
X = 2
Y = 1
Prefab3
Y = 4
Nested Prefabのオーバーライド
X = 2
Prefab1 X = 2
Y = 12
Prefab2
オーバーライドした値が優先される点には注意
X = 2
Y = 12
Prefab3
Y = 4
“ ”
DEMO
Prefabのバリアント
Variant =本質的には同じものだが、

少しずつ異なるPrefab
Prefabを元にPrefabを生成
大体同じだが、
異なる設定を持つPrefab
X = 1
Prefab1
Y = 1
X = 1
Prefab1
Y = 1
X = 1
Prefab2
Y = 1
Variantを作成
X = 1
Prefab1
Y = 1
X = 2
Prefab2
Y = 1
個別に値をオーバーライドできる
X = 1
Prefab1
Y = 5
X = 2
Prefab2
Y = 5
大本Prefabを更新すると、反映される
“ ”
DEMO
Prefab
ボーン構造
コンポーネント
追加した
子オブジェクト
モデルの更新
メッシュ
Model
Prefabを自動生成
(FBX)
元Prefab
ボーン構造
コンポーネント コンポーネント
追加した
子オブジェクト
追加した
子オブジェクト
ボーン構造
モデルの更新(いままで)
メッシュ
Prefab
メッシュ
構造が異なると作り直し
元Prefab
ボーン構造
コンポーネント コンポーネント
追加した
子オブジェクト
追加した
子オブジェクト
ボーン構造
モデルの更新
メッシュ メッシュ
モデルのオブジェクトが独立
オブジェクトを更新すると反映
Prefab
ここが変わった!
Prefabを細かく分割しやすくなった!
Nested
Prefab
バリアント Prefabの一括更新がやりやすくなった
バリエーションを作るときにスクリプトとか無くてもなんとかなる
編集した時の動作
モデルの更新もやりやすくなった
Addressable 

Asset System
動的なメモリマネジメント
依存関係の制御
ダイナミックなコンテンツの配信
アセットの参照をもっと簡単に
繰り返し確認しやすく
Resources
普通にアセットを参照するのはすごく簡単
Prefab
Texture
Model
Material
Prefab Texture
Audio Shader
アセットを参照すると、自動的にロードされてしまう
• とはいえAssetBundleにすると途端に面倒くさい事になる
• 直接参照

SceneやPrefabからアセットへ直接参照する

関連するアセットが速やかに根こそぎロードされる

• Resources

名前ベースで指定したアセットをロードする。(現在非推奨)

• AssetBundle

アセットを外部ファイルにまとめて配信する

バージョン、キャッシュ、依存関係、アセット格納先、開放タイミング等、考えることが多い
直接参照か、ResourcesかAssetBundleか
• 直接参照

完全に関係のあるアセット

即座にアセットがロードされる

• Addressable Asset System

関係の薄いアセット

格納場所を気にせずアセットをロードできる
直接参照か、ResourcesかAssetBundleか
直接参照、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;
player.Instantiate<GameObject>().Completed += (op) =>
{playerInstance = op.Result;}
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
オブジェクトの破棄
Addressables.ReleaseInstance(playerInstance);
Addressables.ReleaseAsset(asset);
Destroy(playerInstance);
Resources.UnloadAsset(asset);
今まで
Addressable
“ ”
DEMO
AssetBundleに登録したアセットの確認
AssetBundleに登録したアセットの確認
AddressableAssetに登録されているアセットの一覧
AssetBundleに登録したアセットの確認
アセットの所属するグループ
グループ毎に配信の形態を設定できる
(サーバー上に配置、StreamingAssetsに配置等)
AssetBundleに登録したアセットの確認
参照のために使用する名前(アドレス)
AssetBundleに登録したアセットの確認
検索や絞り込みに使用されるラベル

(複数登録可)
ラベルに指定したアセットの事前ロード
var preloadOp = Addressables.PreloadDependencies("preload", null);
yield return preloadOp;
“preload”のラベルを持つアセットを
事前にロードしておく
ラベルを指定したアセット一覧を取得
var op = Addressables.LoadAssets<IResourceLocation>(hazardsLabel.labelString, null);
yield return op;
hazardLocations = new List<IResourceLocation>(op.Result);
public AssetLabelReference hazardsLabel;
アドレスから直接オブジェクトを生成する
Addressables.Instantiate<GameObject>("Done_Player");
データの格納場所はグループ単位
グループ毎にAssetBundleを
配置するパスを指定
ローカル or サーバー等
プロファイル
接続先を複数用意しておき、
選択一つで切替可能
ステージング用、本番用等
格納方式もグループ単位
pack Separately
1Addressable 1AssetBundle
pack Together
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 AssetBundleへの参照がResourcesや直接参照並みに簡単に
Virtual / Fastモード AssetBundleビルド待ちせず調整が可能に
メモリ管理
検証がやりやすくなった
参照カウンターで自動的に開放される
色々考えなくても良い感じによしなにしてくれるようになった
Addressable、ResourceManagerの拡張
AddressableはC#

PackageManagerで提供されている
つまり改造できる
“ ”
今までアセット制御のために

多くのスクリプトを要求していた
“ ”
AddressableとNew Prefab Workflowで
特別なコードを書かなくとも
良い感じにアセットを制御しやすくなった
“ ”
今後は、色々面倒なことしなくても、
素直にアセットの作成や量産、読込が可能に!
Thank you!
ご静聴ありがとうございました

【CEDEC2018】ココが変わる!Unityの新しいエディタワークフロー