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.
Extending the Unity Editor                    Unity Editor の 拡張について
Extending the Unity Editor まずはUnityのGUIを理解しよう (1/2) ・基本的にデバッグ用    毎フレーム1つ1つのコンポーネントについて判定・再描画が    行われるので重い。また使いこなすにはGUISki...
Extending the Unity Editor まずはUnityのGUIを理解しよう (2/2) ・OnGUI()に表示と処理を一緒くたに書く    ゲーム実行中に、ゲームオブジェクトの更新と描画が終わった    タイミングでOnGUI(...
Extending the Unity Editor GUIとGUILayout (1/2) ・GUI = 自由配置    第一引数が必ず、位置とサイズを指定するためのRect構造体。     void OnGUI()     {       ...
Extending the Unity Editor GUIとGUILayout (2/2) ・GUILayout = 逐次配置    書いていった順に並んで表示される。BeginHorizontalなどで    グループ化して並べることも可能...
Extending the Unity Editor EditorGUIとEditorGUILayout (1/2) ・GUI・GUILayoutの関係と同じ    EditorGUIは絶対座標指定、EditorGUILayoutは逐次配置。 ...
Extending the Unity Editor EditorGUIとEditorGUILayout (2/2) ・基本的にEditorGUILayoutを使用    ゲーム用のGUIがゲーム画面の左上を基準にして配置されるよ    うに、...
Extending the Unity Editor インスペクタを拡張してみよう (1/5) ・何を拡張できるの?    インスペクタに表示されるものなら何でも。    選択中のオブジェクトに対する操作やインスペクタでの表示の    され方を...
Extending the Unity Editor インスペクタを拡張してみよう (2/5) ・どう拡張できるの?    例えば左のようなプロパティを持つコンポーネントを作ったと    する。するとインスペクタでの表示は右のようになる。   ...
Extending the Unity Editor インスペクタを拡張してみよう (3/5) ・拡張エディタクラスを定義する    エディタのProject直下(フォルダ構成としてはAssets直下)に    Editorという名前のフォルダ...
Extending the Unity Editor インスペクタを拡張してみよう (4/5) ・拡張エディタクラスを実装する    EditorGUILayoutには、そのものズバリVector3Fieldという    パーツが用意されている...
Extending the Unity Editor インスペクタを拡張してみよう (5/5) ・拡張エディタクラスを堪能する    Unityにフォーカスを戻してコンパイルエラーなどがなければ、    インスペクタの表示が以下のように変化して...
Extending the Unity Editor もっと拡張してみよう (1/2) ・リセット・コピー&ペーストの実装    先ほどのプロパティをゼロリセットするボタンと、数値を別の    オブジェクトにコピー&ペーストするボタンを付けてみ...
Extending the Unity Editor もっと拡張してみよう (2/2) ・挙動の確認    Unityにフォーカスを戻してコンパイルエラーなどがなければ、    インスペクタの表示が以下のように変化している。          ...
Extending the Unity Editor 他にもこんな便利なパーツが ・範囲指定    EditorGUILayout.MinMaxSlider() ・ゲージ表示    EditorGUI.ProgressBar()        ...
Extending the Unity Editor 拡張インスペクタの振る舞い (1/2) ・必要な時にnewされている    先ほど実装した拡張インスペクタは、Unityエディタ上で対象の    コンポーネントがアタッチされているオブジェク...
Extending the Unity Editor 拡張インスペクタの振る舞い (2/2) ・必要な時にOnInspectorGUI()が呼ばれる    OnGUI()が毎フレーム呼ばれるのと違い、OnInspectorGUI()    はイ...
Extending the Unity Editor シーンビューも拡張してみよう (1/3) ・ハンドル(マニピュレータ)の表示    ベクトルを下図のようにグラフィカルに表示したい。                             ...
Extending the Unity Editor シーンビューも拡張してみよう (2/3) ・ハンドル(マニピュレータ)の表示    拡張インスペクタで取り扱っている情報を、シーンビュー上に    グラフィカルに表示すると理解しやすくなる場...
Extending the Unity Editor シーンビューも拡張してみよう (3/3) ・ハンドル(マニピュレータ)の表示    ベクトルがグラフィカルに表示されるようになった。                             ...
Extending the Unity Editor 拡張インスペクタの例                             21/30
Extending the Unity Editor ウィンドウを作ってみよう (1/5) ・何を拡張できるの?    Build Settingのようなフローティングウィンドウや、    AnimationウィンドウのようなDock可能なウィ...
Extending the Unity Editor ウィンドウを作ってみよう (2/5) ・Floatingウィンドウの場合     public sealed class MaterialReplacer : EditorWindow   ...
Extending the Unity Editor ウィンドウを作ってみよう (3/5) ・Dockableウィンドウの場合     public sealed class MaterialReplacer : EditorWindow   ...
Extending the Unity Editor ウィンドウを作ってみよう (4/5) ・OnGUI()にレイアウトを実装    拡張インスペクタと同じ要領で、OnGUI()をオーバーライドし    そこへレイアウトを入れこんでいく。   ...
Extending the Unity Editor ウィンドウを作ってみよう (5/5) ・ウィンドウが完成    選択中のゲームオブジェクト全てのマテリアルを、指定した    ものに差し替えるツールが完成。        マテリアルを選択し...
Extending the Unity Editor 覚えておきたい (1/4) ・Selectionクラス    エディタ上で選択中のオブジェクトには、Selectionクラスを    通してアクセスできる。                 ...
Extending the Unity Editor 覚えておきたい (2/4) ・Undoクラス    スクリプトから変更した情報は、何もしないとUndoの履歴に    残らない。エディタの拡張をする場合はUndo.RegisterUndo ...
Extending the Unity Editor 覚えておきたい (3/4) ・EditorUtility、FileUtilなどのユーティリティ    EditorUtilityにはファイルオープンダイアログやYes/No形式    のダイ...
Extending the Unity Editor 覚えておきたい (4/4) ・ファイル出力やシステムコールも可能    System.IO.StreamWriterを使ってgmcs.rspを書きだしたり    System.Diagnos...
Upcoming SlideShare
Loading in …5
×

Extending the Unity Editor

55,435 views

Published on

  • Be the first to comment

Extending the Unity Editor

  1. 1. Extending the Unity Editor Unity Editor の 拡張について
  2. 2. Extending the Unity Editor まずはUnityのGUIを理解しよう (1/2) ・基本的にデバッグ用 毎フレーム1つ1つのコンポーネントについて判定・再描画が 行われるので重い。また使いこなすにはGUISkinなどの細かい 仕様を覚えなくてはならず面倒。 ・Viewport空間ではなくScreen空間に描画 スクリーンに対する絶対座標で描画されるので、画面解像度が 変わった時に破綻する。 ・フォントの問題 PC/Mac以外で日本語文字を表示しようとすると非常に面倒。 携帯機ではDynamicフォントが使えない。 2/30
  3. 3. Extending the Unity Editor まずはUnityのGUIを理解しよう (2/2) ・OnGUI()に表示と処理を一緒くたに書く ゲーム実行中に、ゲームオブジェクトの更新と描画が終わった タイミングでOnGUI()が呼ばれ、そこに記述されている内容が 実行される。 void OnGUI() { if (GUILayout.Button("Next Level")) { Application.LoadLevel("Level2"); } if (GUILayout.Button("Quit")) { Application.Quit(); } } ・拡張エディタの場合もこの辺の仕組みは同じ インスペクタやウィンドウの再描画が必要なタイミングで、 OnInspectorGUI()やOnGUI()が呼ばれる。 3/30
  4. 4. Extending the Unity Editor GUIとGUILayout (1/2) ・GUI = 自由配置 第一引数が必ず、位置とサイズを指定するためのRect構造体。 void OnGUI() { GUI.Button(new Rect(10, 10, 100, 50), "Button1"); GUI.Button(new Rect(50, 50, 100, 50), "Button2"); GUI.Button(new Rect(90, 90, 100, 50), "Button3"); text = GUI.TextArea(new Rect(200, 10, 100, 100), text); } 4/30
  5. 5. Extending the Unity Editor GUIとGUILayout (2/2) ・GUILayout = 逐次配置 書いていった順に並んで表示される。BeginHorizontalなどで グループ化して並べることも可能。 void OnGUI() { GUILayout.BeginHorizontal(); //水平方向にグループ化 GUILayout.BeginVertical(); //垂直方向にグループ化 GUILayout.Button("Button1"); GUILayout.Button("Button2"); GUILayout.Button("Button3"); GUILayout.EndVertical(); text = GUILayout.TextArea(text, GUILayout.Width(200), GUILayout.Height(60)); GUILayout.EndHorizontal(); } ※インデントは気分。必須ではない。 5/30
  6. 6. Extending the Unity Editor EditorGUIとEditorGUILayout (1/2) ・GUI・GUILayoutの関係と同じ EditorGUIは絶対座標指定、EditorGUILayoutは逐次配置。 Editor向けに便利なパーツが用意されている。 ・GUI系とEditorGUI系は混在可能 というよりEditorGUIにはButton等の基本的なパーツはなく、 GUI系と混在させて使うことが前提。 public override void OnInspectorGUI() { GUILayout.BeginHorizontal(); position = EditorGUILayout.Vector3Field("Position", position); if (GUILayout.Button("Reset")) position = Vector3.zero; GUILayout.EndHorizontal(); } 6/30
  7. 7. Extending the Unity Editor EditorGUIとEditorGUILayout (2/2) ・基本的にEditorGUILayoutを使用 ゲーム用のGUIがゲーム画面の左上を基準にして配置されるよ うに、エディタ用のGUIはインスペクタやウィンドウの左上を 基準にして配置されていく。 座標を全部自前で計算してもいいが、EditorGUILayoutで配置 しておくとスケーリングが自動で行われるのでスマート。 ・位置調整用のパーツもある 領域のサイズを考慮して自動的に伸縮するFlexibleSpace()や 逆に勝手に伸縮しないようにするGUILayout.ExpandWidth() を上手く使ってかっこ良く配置しよう。 7/30
  8. 8. Extending the Unity Editor インスペクタを拡張してみよう (1/5) ・何を拡張できるの? インスペクタに表示されるものなら何でも。 選択中のオブジェクトに対する操作やインスペクタでの表示の され方を独自に記述可能。 ・コンポーネントごとに拡張クラスを定義 拡張インスペクタはインスペクタ全体ではなくTransformとか Cameraとかの各コンポーネント毎にクラスを定義していく。 using UnityEngine; // 必須 using UnityEditor; // 必須 [CustomEditor(typeof(Transform))] // Transformクラス用の拡張であることを表すアトリビュート public sealed class CustomTransformEditor : Editor // Editorクラスを継承する { public override void OnInspectorGUI() // インスペクタが再描画されるタイミングで呼ばれる { ... 8/30
  9. 9. Extending the Unity Editor インスペクタを拡張してみよう (2/5) ・どう拡張できるの? 例えば左のようなプロパティを持つコンポーネントを作ったと する。するとインスペクタでの表示は右のようになる。 using UnityEngine; public class Hoge : MonoBehaviour { public Vector3 velocity; } これではVectorの各要素が縦に並んでいて非常に無様である。 しかも初期状態では折りたたまれているし、色々ひどい。 これをTransformの表示のように横に並べたい。 すっきり! 9/30
  10. 10. Extending the Unity Editor インスペクタを拡張してみよう (3/5) ・拡張エディタクラスを定義する エディタのProject直下(フォルダ構成としてはAssets直下)に Editorという名前のフォルダを作り、そこに新規スクリプトを 配置。MonoBehaviour向けに書かれている内容をEditor向け に書きなおす。 using UnityEngine; // 必須 using UnityEditor; // 必須 [CustomEditor(typeof(Hoge))] // Hogeクラス用の拡張であることを宣言 public sealed class HogeEditor : Editor { public override void OnInspectorGUI() { DrawDefaultInspector(); // とりあえずデフォルトの表示 } } 10/30
  11. 11. Extending the Unity Editor インスペクタを拡張してみよう (4/5) ・拡張エディタクラスを実装する EditorGUILayoutには、そのものズバリVector3Fieldという パーツが用意されているのでそれを利用。 using UnityEngine; using UnityEditor; [CustomEditor(typeof(Hoge))] public sealed class HogeEditor : Editor { public override void OnInspectorGUI() { // 今インスペクタで表示しているオブジェクトのインスタンスがtargetに格納されている Hoge hoge = target as Hoge; // targetプロパティはObject型なので目的の型にキャスト Vector3 v = EditorGUILayout.Vector3Field("Velocity", hoge.velocity); if (v != hoge.velocity) // 変更があった場合のみ処理する { Undo.RegisterUndo(hoge, "Velocity Change"); // アンドゥバッファに登録 hoge.velocity = v; EditorUtility.SetDirty(target); // アセットデータベースに変更を通知 } } } 11/30
  12. 12. Extending the Unity Editor インスペクタを拡張してみよう (5/5) ・拡張エディタクラスを堪能する Unityにフォーカスを戻してコンパイルエラーなどがなければ、 インスペクタの表示が以下のように変化している。  Undo.RegisterUndo()して  あるので、Ctrl+Zで取り消し、  Ctrl+Yでやり直しもバッチリ。 12/30
  13. 13. Extending the Unity Editor もっと拡張してみよう (1/2) ・リセット・コピー&ペーストの実装 先ほどのプロパティをゼロリセットするボタンと、数値を別の オブジェクトにコピー&ペーストするボタンを付けてみる。 static Vector3 copyBuffer = Vector3.zero; public override void OnInspectorGUI() { Hoge hoge = target as Hoge; Vector3 v = EditorGUILayout.Vector3Field("Velocity", hoge.velocity); EditorGUILayout.BeginHorizontal(); // 水平方向に並べる if (GUILayout.Button("Reset", EditorStyles.miniButton)) // 見た目にこだわってみる v = Vector3.zero; GUILayout.Space(GUILayoutUtility.GetAspectRect(1).width / 3); if (GUILayout.Button("Copy", EditorStyles.miniButtonLeft)) copyBuffer = v; if (GUILayout.Button("Paste", EditorStyles.miniButtonRight)) v = copyBuffer; EditorGUILayout.EndHorizontal(); if (v != hoge.velocity) { Undo.RegisterUndo(hoge, "Velocity Change"); hoge.velocity = v; EditorUtility.SetDirty(target); } } 13/30
  14. 14. Extending the Unity Editor もっと拡張してみよう (2/2) ・挙動の確認 Unityにフォーカスを戻してコンパイルエラーなどがなければ、 インスペクタの表示が以下のように変化している。  EditorStylesの指定や空白を  配置したことで、まとまりの  ある見た目にする事ができた。 14/30
  15. 15. Extending the Unity Editor 他にもこんな便利なパーツが ・範囲指定 EditorGUILayout.MinMaxSlider() ・ゲージ表示 EditorGUI.ProgressBar() 15/30
  16. 16. Extending the Unity Editor 拡張インスペクタの振る舞い (1/2) ・必要な時にnewされている 先ほど実装した拡張インスペクタは、Unityエディタ上で対象の コンポーネントがアタッチされているオブジェクトが選択され る度にnewされている。 従って、1つのオブジェクトを選択している間はインスペクタ 自体のメンバプロパティは保持されるが、別のオブジェクトを 選択するとインスペクタのメンバは初期値に戻る。 複数オブジェクトをまたいでやりとりしたい情報がある場合は staticメンバを利用しよう。 またOnEnable()をオーバーライドすることで、オブジェクト を選択した瞬間の挙動を定義することも可能。 16/30
  17. 17. Extending the Unity Editor 拡張インスペクタの振る舞い (2/2) ・必要な時にOnInspectorGUI()が呼ばれる OnGUI()が毎フレーム呼ばれるのと違い、OnInspectorGUI() はインスペクターペインの再描画が必要になったタイミングで 随時呼ばれている。 従って「一定間隔で明滅する」といったような、エディタ上で リアルタイムに何かを動かすような処理は基本的にできない。 (毎回Repaint()を呼びまくれば可能ではある) ・シーンビューの更新時にはOnSceneGUI() インスペクタの親クラスであるEditorにはOnSceneGUI()と いうメソッドもあり、これはシーンビューが更新されるときに 呼ばれている。どう使うのかというと… 17/30
  18. 18. Extending the Unity Editor シーンビューも拡張してみよう (1/3) ・ハンドル(マニピュレータ)の表示 ベクトルを下図のようにグラフィカルに表示したい。 18/30
  19. 19. Extending the Unity Editor シーンビューも拡張してみよう (2/3) ・ハンドル(マニピュレータ)の表示 拡張インスペクタで取り扱っている情報を、シーンビュー上に グラフィカルに表示すると理解しやすくなる場合がある。 [CustomEditor(typeof(Hoge))] public sealed class HogeEditor : Editor { Hoge hoge = null; void OnEnable() { hoge = target as Hoge; } void OnSceneGUI() { Vector3 root = hoge.transform.position; // 起点を計算 Vector3 cap = root + hoge.velocity; // 終点を計算 Handles.color = Color.magenta; // 色を変更 Handles.DrawLine(root, cap); // 線を描画 Quaternion rot = Quaternion.LookRotation(hoge.velocity); // 終点の向きを計算 float size = HandleUtility.GetHandleSize(cap); // カメラ距離に依らないサイズを計算 Handles.ArrowCap(0, cap, rot, size); // 矢印型の終点を描画 } static Vector3 copyBuffer = Vector3.zero; public override void OnInspectorGUI() 19/30
  20. 20. Extending the Unity Editor シーンビューも拡張してみよう (3/3) ・ハンドル(マニピュレータ)の表示 ベクトルがグラフィカルに表示されるようになった。 20/30
  21. 21. Extending the Unity Editor 拡張インスペクタの例 21/30
  22. 22. Extending the Unity Editor ウィンドウを作ってみよう (1/5) ・何を拡張できるの? Build Settingのようなフローティングウィンドウや、 AnimationウィンドウのようなDock可能なウィンドウ、 あるいは簡単なウィザードなどを独自に作ることができる。 ・ウィンドウごとに拡張クラスを定義 カスタムウィンドウは拡張インスペクタと違い、ウィンドウ 1つ1つが独立したインスタンスとして振舞う。 using UnityEngine; // 必須 using UnityEditor; // 必須 public sealed class MaterialReplacer : EditorWindow // EditorWindowクラスを継承する { [MenuItem("Tool/Replace Material...")] // エディタのメニューに項目が追加される static void OpenWindow() // 上記項目をクリックするとこの関数が呼ばれる { 22/30
  23. 23. Extending the Unity Editor ウィンドウを作ってみよう (2/5) ・Floatingウィンドウの場合 public sealed class MaterialReplacer : EditorWindow { [MenuItem("Tool/Replace Material...")] static void OpenWindow() // メニューから呼ばれるためにはstatic関数でなければならない { EditorWindow.GetWindow<MaterialReplacer>(true, "Replace Material"); } } 23/30
  24. 24. Extending the Unity Editor ウィンドウを作ってみよう (3/5) ・Dockableウィンドウの場合 public sealed class MaterialReplacer : EditorWindow { [MenuItem("Tool/Replace Material...")] static void OpenWindow() // メニューから呼ばれるためにはstatic関数でなければならない { EditorWindow.GetWindow<MaterialReplacer>(false, "Replace Material"); } } Dock可能 24/30
  25. 25. Extending the Unity Editor ウィンドウを作ってみよう (4/5) ・OnGUI()にレイアウトを実装 拡張インスペクタと同じ要領で、OnGUI()をオーバーライドし そこへレイアウトを入れこんでいく。 [MenuItem("Tool/Replace Material...")] static void OpenWindow() { EditorWindow.GetWindow<MaterialReplacer>(false, "Replace Material"); } static Material targetMaterial = null; void OnGUI() { targetMaterial = EditorGUILayout.ObjectField( "Material", targetMaterial, typeof(Material), false ) as Material; GUI.enabled = (targetMaterial != null) && (Selection.gameObjects.Length > 0); if (GUILayout.Button("Replace!")) { foreach (var renderer in from go in Selection.gameObjects select go.renderer) if (renderer != null) renderer.sharedMaterial = targetMaterial; } GUI.enabled = true; } 25/30
  26. 26. Extending the Unity Editor ウィンドウを作ってみよう (5/5) ・ウィンドウが完成 選択中のゲームオブジェクト全てのマテリアルを、指定した ものに差し替えるツールが完成。 マテリアルを選択し、差し替え たいオブジェクトを選択状態に したらReplaceボタンを押す 選択中のオブジェクトにレンダラが付い ていれば、そのマテリアルが差し替わる 26/30
  27. 27. Extending the Unity Editor 覚えておきたい (1/4) ・Selectionクラス エディタ上で選択中のオブジェクトには、Selectionクラスを 通してアクセスできる。 27/30
  28. 28. Extending the Unity Editor 覚えておきたい (2/4) ・Undoクラス スクリプトから変更した情報は、何もしないとUndoの履歴に 残らない。エディタの拡張をする場合はUndo.RegisterUndo を有効に使い、ユーザーの利便性を図ろう。 28/30
  29. 29. Extending the Unity Editor 覚えておきたい (3/4) ・EditorUtility、FileUtilなどのユーティリティ EditorUtilityにはファイルオープンダイアログやYes/No形式 のダイアログを表示するためのメソッド、FileUtilにはファイル のコピーや削除などを行うメソッドなど、色々便利なインター フェースが用意されている。 ・スクリプトから全ての設定にアクセス可能 PlayerSettingsやEditorUserBuildSettingsなどを通して、 エディタ上で触れる設定項目は全てスクリプトからも操作が 可能。面倒な処理はバッチ化してしまえ。 29/30
  30. 30. Extending the Unity Editor 覚えておきたい (4/4) ・ファイル出力やシステムコールも可能 System.IO.StreamWriterを使ってgmcs.rspを書きだしたり System.Diagnostics.Processを使ってシステムコールを 呼び出すことも可能。Unity組み込みのWWWクラスを使って 簡単にウェブサーバと連携したり、可能性は無限大。 30/30

×