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.

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

995 views

Published on

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

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

Published in: Technology
  • Be the first to comment

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

  1. 1. 新しいPrefab
 ワークフロー再入門 Tatsuhiko Yamamura @ Unity
  2. 2. 人は
 Nested Prefabと
 和解できるのか?
  3. 3. Unityの代表機能 Prefab…を始めとしたアセット管理、コンテンツ配信機能
  4. 4. Prefabという機能 インスタンス アセット
 (Prefab) • GameObjectをアセットに変換したもの
  5. 5. Prefabという機能 シーンにセットアップ済み オブジェクトを配置 アセット
  6. 6. Prefabという機能 Texture Audio Mesh 必要なアセットを
 一緒にロードする C#
  7. 7. Prefabという機能 Asset Bundle
 Resources 「アセット」として格納 取り出して動的に生成 Game
  8. 8. Prefabという機能 ATK : 100 DEF : 30 ATK : 100 DEF : 30 Prefabを変更すれば、
 Sceneに配置した
 オブジェクトに反映される ATK : 100 DEF : 30
  9. 9. Prefabという機能 Prefab配置 Prefab差替
  10. 10. Prefabという機能 A B C Aを編集する人 Bを編集する人 Sceneを
 編集する人 • 分業がやりやすい
  11. 11. Prefabという機能 A B C A B B • Prefabを配置して Prefabを
 配置
  12. 12. A B B B A Prefabという機能 C • 中身を差し替える
  13. 13. Scene内でユニークな値を持つ X : 1 Y : 1 X : 1 Y : 1 InstancePrefab 配置
  14. 14. X : 1 Y : 1 X : 1 Y : 1 InstancePrefab 4 Scene内でユニークな値を持つ
  15. 15. Prefabの編集 • 二通りの方法 • Scene上に配置後、変更してからアセットに反映 • アセットをPrefabエディターで直接編集
  16. 16. Prefabの編集 Scene上で変更して
 Applyボタンを押す 一番親のPrefabのみ
 Applyボタンが表示
  17. 17. Prefabの編集 Prefabエディターで
 個別に変更
  18. 18. Prefabの階層構造 Prefab Prefab Prefab Nested
  19. 19. Player prefab Gun prefab Player担当 Gun担当 Prefabの階層構造 Prefabが他のPrefabを保持
  20. 20. D2 Prefab D1 Prefab Player Prefab Gun prefab (Gun Prefabを持つ) (Gun Prefabを持つ) (Gun Prefabを持つ) 各ユニットが
 GUNを持てる Prefabの階層構造 各ユニットが
 GUNを持てる 各ユニットが
 GUNを持てる
  21. 21. D2 PrefabD1 Prefab Player Prefab Gun prefab (Gun Prefabを持つ)(Gun Prefabを持つ) (Gun Prefabを持つ) Prefabに格納していても
 武器のステータス変更が
 反映される Prefabの階層構造
  22. 22. Prefabの階層構造 Player
 prefab Instantiate Scene Instance 使う側はネストを気にしなくても良い
  23. 23. Prefabのバリアント Variant:(他とは少し)異なるもの。亜種
  24. 24. Prefabのバリアント • キャラクター名:ユニティちゃん • LV : 1 • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 9999
  25. 25. Prefabのバリアント あと2種類のキャラクターを作りたい • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 9999
  26. 26. • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 9999 Prefabのバリアント キャラクターを量産 • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 9999
  27. 27. • HP : 9999 • MP : 9999 • ATK : 9999 •DEF : 10 Prefabのバリアント • HP : 9999 • MP : 9999 •ATK : 10 • DEF : 9999 ビジュアル、パラメーターの調整 Prefab毎に設定を持てる
  28. 28. • HP : 9999 • MP : 9999 • ATK : 9999 • DEF : 10 Prefabのバリアント • HP : 9999 • MP : 9999 • ATK : 10 • DEF : 9999 •HP : 100 •MP : 100 • ATK : 9999 • DEF : 9999
  29. 29. •HP : 100 •MP : 100 • ATK : 9999 • DEF : 10 Prefabのバリアント •HP : 100 •MP : 100 • ATK : 10 • DEF : 9999 •HP : 100 •MP : 100 • ATK : 9999 • DEF : 9999 親Prefabの値を追跡できる
  30. 30. Prefabのバリアント 比較的少ない手間でキャラを量産できる
  31. 31. もう少し詳しい話 入門の時間は終わりだ…
  32. 32. Prefabとハンドル X : 1 Y : 1 Z : 1 X : 1 Y : 1
 Z : 1 InstancePrefab 32
  33. 33. Prefabとハンドル X : 1 Y : 1 Z : 1 InstancePrefab ID :123 ID : 123 X :132
  34. 34. Nested Prefabとハンドル Prefab B Prefab O Prefab A ………… A : 16 B : 8 X : 1 Y : 1 Z : 1 32
  35. 35. Nested Prefabとハンドル A : 12
 Prefab O B : 8
 Prefab A Prefab A X : 1 Y : 1 Z : 1 Prefab B Prefab B 32
  36. 36. Nested Prefabとハンドル X : 1 Y : 1 Z : 1 A : 12
  B : 8  (Xを32へ変更) ID :123ID :456ID :789 ID : 123 ID : 456
  37. 37. Nested Prefabとハンドル 親PrefabのYAML 子PrefabのYAML
  38. 38. Nested Prefabとハンドル (Xを32へ変更) ID :789 ID : 123 X : 1 Y : 1 Z : 1 ID :123
  39. 39. Nested Prefabとハンドル • 親Prefabが上書き出来る
 子Prefabの設定 • パラメーターの変更 • Componentの追加・削除 • GameObjectの追加 • 親Prefabが出来ない操作
 • GameObjectの順番変更 • Componentの順番変更 • GameObjectの削除
  40. 40. Nested Prefabとハンドル • Prefabのオブジェクト構造を変更したい場合 • Variantを作り、Prefabエディターで
 構造を変更する • Prefabエディターで構造を変更する • Unpack prefabでハンドルを消す
  41. 41. ビルド後の動き Prefab A Prefab B ………… Prefab C ………… Prefab A Prefab B ………… Prefab C ………… ビルド後 • ビルドするとPrefabはシーンにベイクされる
  42. 42. ビルド後の動き • AssetBundleに格納した場合、統合される Prefab A ID : Prefab C Prefab B Prefab A Prefab Cビルド後 Prefab C ID : Prefab C Prefab B Prefab C
  43. 43. ビルド後の動き Variantの場合も同様 Xを999へ上書き X : 12 Y : 15 Z : 32 ビルド後 X : 999 Y : 15 Z : 32 ID : 123 ID : 123 ID : 456
  44. 44. ビルド後の動き CubeCube Variant 生成 Autoとして
 含まれるように見えるが… 実際には含まれない VariantのPrefabを
 作成してAssetBundleに格納
  45. 45. Nested Prefabと
 付き合うポイント
  46. 46. 必要な項目のみ変更 • 変更する内容が少なければ、
 ファイル同士の競合頻度を減らせる •HP : 100 • MP : 50 • HP : 20 •MP : 50
  47. 47. 必要な項目のみ変更 上書きしているパラメータには青い線がつく
  48. 48. 必要な項目のみ変更 変更前と変更後の値の比較
  49. 49. 必要な項目のみ変更 値は個別に反映を設定
  50. 50. 必要な項目のみ変更 • Prefabエディターは
 変更した値が全て更新される • 変更した値がドレか分からない
 (直接操作しているため、
 値を上書きしたときのマーカーが出ない) • YAML Mergeで競合を減らす • バリアント経由で操作する
  51. 51. 必要な項目のみ変更 • PrefabエディターではApplyするな
  52. 52. Applyの対象 Prefab Prefab Prefab • Sceneでの変更は
 Applyで反映される • バリアントの場合や
 階層化してる場合は…
  53. 53. Applyの対象 • Sceneでの変更は
 Applyで反映される • バリアントの場合や
 階層化してる場合は…
 反映するPrefabを選択する
  54. 54. Applyの対象 ID : 456 ID : 123 X : 1 ID : 123ID : 456
  55. 55. Applyの対象 ID : 456 ID : 123 X : 1 ID : 123ID : 456 X : 1X : 1X : 1
  56. 56. Applyの対象 ID : 456 X:1を2に ID : 123 X : 1 ID : 123ID : 456
  57. 57. X:1を2に Applyの対象 ID : 456 ID : 123 X : 1 ID : 123ID : 456 X : 1X : 2X : 2
  58. 58. Applyの対象 X:1を3に ID : 456 ID : 123 X : 1 ID : 123ID : 456
  59. 59. Applyの対象 X:1を3に ID : 456 ID : 123 X : 1 ID : 123ID : 456 X : 1X : 1X : 3
  60. 60. Applyの対象 X:1を3に ID : 456 ID : 123 X : 1 ID : 123ID : 456 自身のPrefab
 のみに影響 Prefabを使用する
 すべてのPrefabに影響
  61. 61. Applyの対象 • Applyの対象は
 何処にすべきか • とりあえず上を
 選択しとけば安定 広い範囲に影響を与える 影響は自分自身のみ
  62. 62. 必要な項目のみ変更 • PrefabエディターではApplyするな Prefabエディターの
 Applyは「親への反映」 自分以外にも影響する
  63. 63. Variantを使え
  64. 64. Variantを使え (猫、動物)ミケ タマ(猫、動物) • 以前は、各Prefabが独立した存在 • Prefabの変更したい場合 • Prefabを選択してから調整 • エディター拡張 • ScriptableObjectとして外部に
 パラメーターを持つ
  65. 65. Variantを使え 動物ネコ ミケ タマ
  66. 66. Variantを使え 動物ネコ ミケ タマ 「動物」に変更を加えれば
 全ての動物を調整出来る ネコは猫独自の
 設定を持てる
  67. 67. Variantを使え • モデルの交換にはVariantを使え Model Name Root … … Renderer
  68. 68. Variantを使え • モデルの交換にはVariantを使え Model Name Root Bone A … ID : 123 ID : 123 RootにColliderを
 追加
  69. 69. Variantを使え • モデルの交換にはVariantを使え Model Name Root Bone A … ID : 123 ID : 123 RootにColliderを
 追加 モデルのボーン構造が
 変わっても追随してくれる
  70. 70. Prefabのバリアント • どのPrefabのバリアントかは確認できるが、命名規則で縛っておいた方が楽
  71. 71. 何故こんなにVariant推しなのか • 「複数選択からの一括パラメーター更新」が出来なくなった • Prefabエディターに全フリしてるせいで面倒なことに…
  72. 72. 何故こんなにVariant推しなのか • 「複数選択からの一括パラメーター更新」が出来なくなった • Prefabエディターに全フリしてるせいで面倒なことに… • Unity 2019.1から複数選択が復活
  73. 73. 2018.3未満からUnity 2018.4へ エディターを更新したい場合… • 複数のPrefabを一気に編集するには…? • 答え① 突如反撃のアイディアがひらめく
     (一旦Sceneに配置すれば複数選択して編集も可能になる等) • 答え② スクリプト自作が助けてくれる • 答え③ 編集できない。現実は非情である。
  74. 74. スクリプトの例
  75. 75. 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);
  76. 76. 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); Prefabの作成 アセットの編集を宣言
  77. 77. 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); Prefabの作成 オブジェクトを生成し、 最後に破棄
  78. 78. 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); Prefabの作成 Prefabとして保存
  79. 79. Immediate Windowで 使い捨てコードを記述して実行
 (本来の使い方とは違うが、便利) Immediate Window
  80. 80. 選択しているオブジェクトの値の変更  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();
  81. 81. 選択しているオブジェクトの値の変更  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(); 操作するオブジェクトの
 絞り込み
  82. 82. 選択しているオブジェクトの値の変更  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(); 実際に操作
  83. 83. フォルダ以下の値の変更 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();
  84. 84. フォルダ以下の値の変更 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(); ファイル一覧を取得
  85. 85. フォルダ以下の値の変更 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(); Prefabコンテンツを
 取得してアンロード
  86. 86. フォルダ以下の値の変更 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(); 中身を更新して反映
  87. 87. その他サンプル https://github.com/Unity-Technologies/PrefabAPIExamples
  88. 88. Nested Prefabと
 和解できた(期待)
  89. 89. おしまい

×