【Unity道場】新しいPrefabワークフロー入門

6.3K Views

June 28, 19

スライド概要

これは2019/6/27 開催のイベント「Unity道場6月〜新しいPrefabワークフロー入門とVectorGraphics〜」の講演資料の一つです。

Nested Prefabを始めとした新しいPrefabワークフローの内容を紹介しています。

profile-image

リアルタイム3Dコンテンツを制作・運用するための世界的にリードするプラットフォームである「Unity」の日本国内における販売、サポート、コミュニティ活動、研究開発、教育支援を行っています。ゲーム開発者からアーティスト、建築家、自動車デザイナー、映画製作者など、さまざまなクリエイターがUnityを使い想像力を発揮しています。

シェア

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

新しいPrefab ワークフロー 入門 再 Tatsuhiko Yamamura @ Unity

2.

人は Nested Prefabと 和解できるのか?

3.

Unityの代表機能 Prefab …を始めとしたアセット管理、コンテンツ配信機能

4.

Prefabという機能 • インスタンス GameObjectをアセットに変換したもの アセット (Prefab)

5.

Prefabという機能 シーンにセットアップ済み オブジェクトを配置 アセット

6.

Prefabという機能 必要なアセットを 一緒にロードする Texture Audio C# Mesh

7.

Prefabという機能 「アセット」として格納 Asset Bundle Game Resources 取り出して動的に生成

8.

Prefabという機能 ATK : 100 Prefabを変更すれば、 Sceneに配置した オブジェクトに反映される ATK : 100 ATK : 100 DEF : 30 DEF : 30 DEF : 30

9.

Prefabという機能 置 配 b a f e r P Prefab差替

10.

Prefabという機能 Aを編集する人 Sceneを A 編集する人 B C Bを編集する人 • 分業がやりやすい

11.

Prefabという機能 Prefabを A A 配置 B C B • Prefabを配置して B

12.

Prefabという機能 A A B C B • 中身を差し替える B

13.

Scene内でユニークな値を持つ 配置 Prefab X:1 Y:1 Instance X:1 Y:1

14.

Scene内でユニークな値を持つ Prefab X:1 Y:1 Instance X:1 Y : 14

15.

Prefabの編集 • 二通りの方法 • Scene上に配置後、変更してからアセットに反映 • アセットをPrefabエディターで直接編集

16.

Prefabの編集 Scene上で変更して Applyボタンを押す 一番親のPrefabのみ Applyボタンが表示

17.

Prefabの編集 Prefabエディターで 個別に変更

18.

Prefabの階層構造 Prefab Prefab Prefab Nested

19.

Prefabの階層構造 Prefabが他のPrefabを保持 Player prefab Player担当 Gun担当 Gun prefab

20.

Prefabの階層構造 D2 Prefab D1 Prefab (Gun Prefabを持つ) (Gun Prefabを持つ) 各ユニットが 各ユニットが 各ユニットが GUNを持てる GUNを持てる GUNを持てる Player Prefab (Gun Prefabを持つ) Gun prefab

21.

Prefabの階層構造 D1 Prefab (Gun Prefabを持つ) D2 Prefab (Gun Prefabを持つ) Prefabに格納していても 武器のステータス変更が 反映される Gun prefab Player Prefab (Gun Prefabを持つ)

22.

Prefabの階層構造 Instance Instantiate Player prefab 使う側はネストを気にしなくても良い Scene

24.

Prefabのバリアント Variant:(他とは少し)異なるもの。亜種

25.

Prefabのバリアント • キャラクター名:ユニティちゃん • LV : 1 • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 9999

26.

Prefabのバリアント あと2種類のキャラクターを作りたい • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 9999

27.

Prefabのバリアント キャラクターを量産 • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 9999 • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 9999

28.

Prefabのバリアント ビジュアル、パラメーターの調整 Prefab毎に設定を持てる • HP : 9999 • MP : 9999 •ATK : 10 • DEF : 9999 • HP : 9999 • MP : 9999 • ATK : 9999 •DEF : 10

29.

Prefabのバリアント •HP : 100 •MP : 100 • ATK : 9999 • DEF : 9999 • HP : 9999 • MP : 9999 • ATK : 10 • DEF : 9999 • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 10

30.

Prefabのバリアント 親Prefabの値を追跡できる •HP : 100 •MP : 100 • ATK : 9999 • DEF : 9999 •HP : 100 •MP : 100 • ATK : 10 • DEF : 9999 •HP : 100 •MP : 100 • ATK : 9999 • DEF : 10

31.

Prefabのバリアント 比較的少ない手間でキャラを量産できる

35.

もう少し詳しい話 入門の時間は終わりだ…

36.

Prefabとハンドル Prefab X:1 Y:1 Z:1 Instance X : 132 Y:1 Z:1

37.

Prefabとハンドル ID :123 Prefab X:1 Y:1 Z:1 Instance ID : 123 X :132

38.

Nested Prefabとハンドル Prefab O A : 16 Prefab A B:8 ………… Prefab B X : 132 Y:1 Z:1

39.

Nested Prefabとハンドル Prefab O A : 12 Prefab A Prefab A Prefab B B:8 Prefab B X : 132 Y:1 Z:1

40.

Nested Prefabとハンドル ID :789 A : 12 ID : 456 ID :456 B:8 ID : 123 (Xを32へ変更) ID :123 X:1 Y:1 Z:1

41.

Nested Prefabとハンドル 親PrefabのYAML 子PrefabのYAML

42.

Nested Prefabとハンドル ID :789 ID :123 ID : 123 X:1 Y:1 Z:1 (Xを32へ変更)

43.

Nested Prefabとハンドル • 親Prefabが上書き出来る 子Prefabの設定 • 親Prefabが出来ない操作 • パラメーターの変更 • GameObjectの順番変更 • Componentの追加・削除 • Componentの順番変更 • GameObjectの追加 • GameObjectの削除

44.

Nested Prefabとハンドル • Prefabのオブジェクト構造を変更したい場合 • Variantを作り、Prefabエディターで 構造を変更する • Prefabエディターで構造を変更する • Unpack prefabでハンドルを消す

45.

ビルド後の動き Prefab A Prefab A Prefab B ………… Prefab B ビルド後 Prefab C ………… • ビルドするとPrefabはシーンにベイクされる ………… Prefab C …………

46.

ビルド後の動き Prefab A ID : Prefab C Prefab B ビルド後 ID : Prefab C Prefab C • AssetBundleに格納した場合、統合される Prefab A Prefab C Prefab B Prefab C

47.

ビルド後の動き ID : 123 Xを999へ上書き ID : 456 ビルド後 X : 12 Y : 15 Z : 32 ID : 123 Variantの場合も同様 X : 999 Y : 15 Z : 32

48.

ビルド後の動き Cube Cube Variant 生成 VariantのPrefabを 作成してAssetBundleに格納 Autoとして 含まれるように見えるが… 実際には含まれない

49.

Nested Prefabと 付き合うポイント

50.

必要な項目のみ変更 • 変更する内容が少なければ、 ファイル同士の競合頻度を減らせる • HP : 20 •MP : 50 •HP : 100 • MP : 50

51.

必要な項目のみ変更 上書きしているパラメータには青い線がつく

52.

必要な項目のみ変更 変更前と変更後の値の比較

53.

必要な項目のみ変更 値は個別に反映を設定

55.

必要な項目のみ変更 • • Prefabエディターは 変更した値が全て更新される 変更した値がドレか分からない (直接操作しているため、 値を上書きしたときのマーカーが出ない) • YAML Mergeで競合を減らす • バリアント経由で操作する

56.

必要な項目のみ変更 • PrefabエディターではApplyするな

57.

Applyの対象 • • Sceneでの変更は Applyで反映される バリアントの場合や 階層化してる場合は… Prefab Prefab Prefab

58.

Applyの対象 • Sceneでの変更は Applyで反映される • バリアントの場合や 階層化してる場合は… 反映するPrefabを選択する

59.

Applyの対象 ID : 456 ID : 456 ID : 123 ID : 123 X:1

60.

Applyの対象 ID : 456 ID : 123 ID : 456 ID : 123 X:1 X:1 X:1 X:1

61.

Applyの対象 ID : 456 ID : 456 ID : 123 ID : 123 X:1を2に X:1

62.

Applyの対象 ID : 456 X:2 ID : 456 ID : 123 ID : 123 X:1を2に X:1 X:2 X:1

63.

Applyの対象 ID : 456 X:1を3に ID : 456 ID : 123 ID : 123 X:1

64.

Applyの対象 ID : 456 X:1を3に X:3 ID : 456 ID : 123 ID : 123 X:1 X:1 X:1

65.

Applyの対象 ID : 456 X:1を3に 自身のPrefab のみに影響 ID : 456 ID : 123 ID : 123 X:1 Prefabを使用する すべてのPrefabに影響

66.

Applyの対象 • Applyの対象は 何処にすべきか • とりあえず上を 選択しとけば安定 影響は自分自身のみ 広い範囲に影響を与える

67.

必要な項目のみ変更 • PrefabエディターではApplyするな Prefabエディターの Applyは「親への反映」 自分以外にも影響する

68.

Variantを使え

69.

Variantを使え タマ (猫、動物) ミケ (猫、動物) • 以前は、各Prefabが独立した存在 • Prefabの変更したい場合 • Prefabを選択してから調整 • エディター拡張 • ScriptableObjectとして外部に パラメーターを持つ

70.

Variantを使え タマ ネコ ミケ 動物

71.

Variantを使え 「動物」に変更を加えれば 全ての動物を調整出来る タマ ネコ ミケ ネコは猫独自の 設定を持てる 動物

72.

Variantを使え • モデルの交換にはVariantを使え Model Name Root … … Renderer

73.

Variantを使え • モデルの交換にはVariantを使え ID : 123 Model Name Root ID : 123 Bone A … RootにColliderを 追加

74.

Variantを使え • モデルの交換にはVariantを使え モデルのボーン構造が 変わっても追随してくれる ID : 123 Model Name Root ID : 123 Bone A … RootにColliderを 追加

76.

Prefabのバリアント • どのPrefabのバリアントかは確認できるが、命名規則で縛っておいた方が楽

77.

何故こんなにVariant推しなのか • 「複数選択からの一括パラメーター更新」が出来なくなった • Prefabエディターに全フリしてるせいで面倒なことに…

78.

何故こんなにVariant推しなのか • 「複数選択からの一括パラメーター更新」が出来なくなった • • Prefabエディターに全フリしてるせいで面倒なことに… Unity 2019.1から複数選択が復活

79.

2018.3未満からUnity 2018.4へ エディターを更新したい場合… • 複数のPrefabを一気に編集するには…? • 答え① 突如反撃のアイディアがひらめく (一旦Sceneに配置すれば複数選択して編集も可能になる等) • 答え② • 答え③ 編集できない。現実は非情である。 スクリプト自作が助けてくれる

80.

スクリプトの例

81.

Prefabの作成 AssetDatabase.StartAssetEditing(); var cube = GameObject.CreatePrimitive(PrimitiveType.Cube); var path = "Assets/Prefabs/Hoge.prefab"; PrefabUtility.SaveAsPrefabAssetAndConnect(cube, path, InteractionMode.AutomatedAction); AssetDatabase.StopAssetEditing(); GameObject.DestroyImmediate(cube);

82.

Prefabの作成 AssetDatabase.StartAssetEditing(); var cube = GameObject.CreatePrimitive(PrimitiveType.Cube); var path = "Assets/Prefabs/Hoge.prefab"; PrefabUtility.SaveAsPrefabAssetAndConnect(cube, path, InteractionMode.AutomatedAction); AssetDatabase.StopAssetEditing(); GameObject.DestroyImmediate(cube); アセットの編集を宣言

83.

Prefabの作成 AssetDatabase.StartAssetEditing(); var cube = GameObject.CreatePrimitive(PrimitiveType.Cube); var path = "Assets/Prefabs/Hoge.prefab"; PrefabUtility.SaveAsPrefabAssetAndConnect(cube, path, InteractionMode.AutomatedAction); AssetDatabase.StopAssetEditing(); GameObject.DestroyImmediate(cube); オブジェクトを生成し、 最後に破棄

84.

Prefabの作成 AssetDatabase.StartAssetEditing(); var cube = GameObject.CreatePrimitive(PrimitiveType.Cube); var path = "Assets/Prefabs/Hoge.prefab"; PrefabUtility.SaveAsPrefabAssetAndConnect(cube, path, InteractionMode.AutomatedAction); AssetDatabase.StopAssetEditing(); Prefabとして保存 GameObject.DestroyImmediate(cube);

85.

Immediate Window Immediate Windowで 使い捨てコードを記述して実行 (本来の使い方とは違うが、便利)

87.
[beta]
選択しているオブジェクトの値の変更
AssetDatabase.StartAssetEditing();
var objs = Selection.gameObjects
.Where(c => PrefabUtility.IsPartOfPrefabAsset(c))
.Where(c => c.GetComponent<Transform>() != null);
foreach( var obj in objs)
{
var transform = obj.transform;
transform.position = new Vector3(0, 12, 0);
}
AssetDatabase.StopAssetEditing();

88.
[beta]
選択しているオブジェクトの値の変更
AssetDatabase.StartAssetEditing();
var objs = Selection.gameObjects
.Where(c => PrefabUtility.IsPartOfPrefabAsset(c))
.Where(c => c.GetComponent<Transform>() != null);
foreach( var obj in objs)
{
var transform = obj.transform;
transform.position = new Vector3(0, 12, 0);
}
AssetDatabase.StopAssetEditing();

操作するオブジェクトの
絞り込み

89.
[beta]
選択しているオブジェクトの値の変更
AssetDatabase.StartAssetEditing();
var objs = Selection.gameObjects
.Where(c => PrefabUtility.IsPartOfPrefabAsset(c))
.Where(c => c.GetComponent<Transform>() != null);
foreach( var obj in objs)
{
var transform = obj.transform;
transform.position = new Vector3(0, 12, 0);
}
AssetDatabase.StopAssetEditing();

実際に操作

90.
[beta]
フォルダ以下の値の変更
var root = "Assets/Prefabs";
var prefabs = System.IO.Directory.GetFiles(root, "*.prefab");
AssetDatabase.StartAssetEditing();
foreach( var path in prefabs)
{
var prefab = PrefabUtility.LoadPrefabContents(path);
prefab.transform.position = new Vector3(0, -1, 0);
PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, path, InteractionMode.AutomatedAction);
PrefabUtility.UnloadPrefabContents(prefab);
}
AssetDatabase.StopAssetEditing();

91.
[beta]
フォルダ以下の値の変更
var root = "Assets/Prefabs";
var prefabs = System.IO.Directory.GetFiles(root, "*.prefab");
AssetDatabase.StartAssetEditing();
foreach( var path in prefabs)
{
var prefab = PrefabUtility.LoadPrefabContents(path);

ファイル一覧を取得

prefab.transform.position = new Vector3(0, -1, 0);
PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, path, InteractionMode.AutomatedAction);
PrefabUtility.UnloadPrefabContents(prefab);
}
AssetDatabase.StopAssetEditing();

92.
[beta]
フォルダ以下の値の変更
var root = "Assets/Prefabs";
var prefabs = System.IO.Directory.GetFiles(root, "*.prefab");
AssetDatabase.StartAssetEditing();
foreach( var path in prefabs)
{
var prefab = PrefabUtility.LoadPrefabContents(path);
prefab.transform.position = new Vector3(0, -1, 0);
PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, path, InteractionMode.AutomatedAction);
Prefabコンテンツを
PrefabUtility.UnloadPrefabContents(prefab);
}
AssetDatabase.StopAssetEditing();

取得してアンロード

93.
[beta]
フォルダ以下の値の変更
var root = "Assets/Prefabs";
var prefabs = System.IO.Directory.GetFiles(root, "*.prefab");
AssetDatabase.StartAssetEditing();
foreach( var path in prefabs)
{
var prefab = PrefabUtility.LoadPrefabContents(path);
prefab.transform.position = new Vector3(0, -1, 0);
PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, path, InteractionMode.AutomatedAction);
PrefabUtility.UnloadPrefabContents(prefab);
}
AssetDatabase.StopAssetEditing();

中身を更新して反映

94.

その他サンプル https://github.com/Unity-Technologies/PrefabAPIExamples

95.

Nested Prefabと 和解できた(期待)

96.

おしまい