SlideShare a Scribd company logo
Extending the Unity Editor
                    Unity Editor の 拡張について
Extending the Unity Editor
 まずはUnityのGUIを理解しよう (1/2)
 ・基本的にデバッグ用
    毎フレーム1つ1つのコンポーネントについて判定・再描画が
    行われるので重い。また使いこなすにはGUISkinなどの細かい
    仕様を覚えなくてはならず面倒。

 ・Viewport空間ではなくScreen空間に描画
    スクリーンに対する絶対座標で描画されるので、画面解像度が
    変わった時に破綻する。

 ・フォントの問題
    PC/Mac以外で日本語文字を表示しようとすると非常に面倒。
    携帯機ではDynamicフォントが使えない。

                                 2/30
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
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
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
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
Extending the Unity Editor
 EditorGUIとEditorGUILayout (2/2)
 ・基本的にEditorGUILayoutを使用
    ゲーム用のGUIがゲーム画面の左上を基準にして配置されるよ
    うに、エディタ用のGUIはインスペクタやウィンドウの左上を
    基準にして配置されていく。
    座標を全部自前で計算してもいいが、EditorGUILayoutで配置
    しておくとスケーリングが自動で行われるのでスマート。

 ・位置調整用のパーツもある
    領域のサイズを考慮して自動的に伸縮するFlexibleSpace()や
    逆に勝手に伸縮しないようにするGUILayout.ExpandWidth()
    を上手く使ってかっこ良く配置しよう。



                                        7/30
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
Extending the Unity Editor
 インスペクタを拡張してみよう (2/5)
 ・どう拡張できるの?
    例えば左のようなプロパティを持つコンポーネントを作ったと
    する。するとインスペクタでの表示は右のようになる。
     using UnityEngine;

     public class Hoge : MonoBehaviour
     {
          public Vector3 velocity;
     }



    これではVectorの各要素が縦に並んでいて非常に無様である。
    しかも初期状態では折りたたまれているし、色々ひどい。
    これをTransformの表示のように横に並べたい。


                                         すっきり!
                                                 9/30
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
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
Extending the Unity Editor
 インスペクタを拡張してみよう (5/5)
 ・拡張エディタクラスを堪能する
    Unityにフォーカスを戻してコンパイルエラーなどがなければ、
    インスペクタの表示が以下のように変化している。

                              Undo.RegisterUndo()して
                              あるので、Ctrl+Zで取り消し、
                              Ctrl+Yでやり直しもバッチリ。




                                                12/30
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
Extending the Unity Editor
 もっと拡張してみよう (2/2)
 ・挙動の確認
    Unityにフォーカスを戻してコンパイルエラーなどがなければ、
    インスペクタの表示が以下のように変化している。

                              EditorStylesの指定や空白を
                              配置したことで、まとまりの
                              ある見た目にする事ができた。




                                              14/30
Extending the Unity Editor
 他にもこんな便利なパーツが
 ・範囲指定
    EditorGUILayout.MinMaxSlider()




 ・ゲージ表示
    EditorGUI.ProgressBar()




                                     15/30
Extending the Unity Editor
 拡張インスペクタの振る舞い (1/2)
 ・必要な時にnewされている
    先ほど実装した拡張インスペクタは、Unityエディタ上で対象の
    コンポーネントがアタッチされているオブジェクトが選択され
    る度にnewされている。

    従って、1つのオブジェクトを選択している間はインスペクタ
    自体のメンバプロパティは保持されるが、別のオブジェクトを
    選択するとインスペクタのメンバは初期値に戻る。

    複数オブジェクトをまたいでやりとりしたい情報がある場合は
    staticメンバを利用しよう。

    またOnEnable()をオーバーライドすることで、オブジェクト
    を選択した瞬間の挙動を定義することも可能。
                                  16/30
Extending the Unity Editor
 拡張インスペクタの振る舞い (2/2)
 ・必要な時にOnInspectorGUI()が呼ばれる
    OnGUI()が毎フレーム呼ばれるのと違い、OnInspectorGUI()
    はインスペクターペインの再描画が必要になったタイミングで
    随時呼ばれている。

    従って「一定間隔で明滅する」といったような、エディタ上で
    リアルタイムに何かを動かすような処理は基本的にできない。
    (毎回Repaint()を呼びまくれば可能ではある)

 ・シーンビューの更新時にはOnSceneGUI()
    インスペクタの親クラスであるEditorにはOnSceneGUI()と
    いうメソッドもあり、これはシーンビューが更新されるときに
    呼ばれている。どう使うのかというと…
                                       17/30
Extending the Unity Editor
 シーンビューも拡張してみよう (1/3)
 ・ハンドル(マニピュレータ)の表示
    ベクトルを下図のようにグラフィカルに表示したい。




                               18/30
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
Extending the Unity Editor
 シーンビューも拡張してみよう (3/3)
 ・ハンドル(マニピュレータ)の表示
    ベクトルがグラフィカルに表示されるようになった。




                               20/30
Extending the Unity Editor
 拡張インスペクタの例




                             21/30
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
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
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
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
Extending the Unity Editor
 ウィンドウを作ってみよう (5/5)
 ・ウィンドウが完成
    選択中のゲームオブジェクト全てのマテリアルを、指定した
    ものに差し替えるツールが完成。




        マテリアルを選択し、差し替え
        たいオブジェクトを選択状態に
        したらReplaceボタンを押す
                             選択中のオブジェクトにレンダラが付い
                             ていれば、そのマテリアルが差し替わる


                                             26/30
Extending the Unity Editor
 覚えておきたい (1/4)
 ・Selectionクラス
    エディタ上で選択中のオブジェクトには、Selectionクラスを
    通してアクセスできる。




                                  27/30
Extending the Unity Editor
 覚えておきたい (2/4)
 ・Undoクラス
    スクリプトから変更した情報は、何もしないとUndoの履歴に
    残らない。エディタの拡張をする場合はUndo.RegisterUndo
    を有効に使い、ユーザーの利便性を図ろう。




                                    28/30
Extending the Unity Editor
 覚えておきたい (3/4)
 ・EditorUtility、FileUtilなどのユーティリティ
    EditorUtilityにはファイルオープンダイアログやYes/No形式
    のダイアログを表示するためのメソッド、FileUtilにはファイル
    のコピーや削除などを行うメソッドなど、色々便利なインター
    フェースが用意されている。

 ・スクリプトから全ての設定にアクセス可能
    PlayerSettingsやEditorUserBuildSettingsなどを通して、
    エディタ上で触れる設定項目は全てスクリプトからも操作が
    可能。面倒な処理はバッチ化してしまえ。




                                              29/30
Extending the Unity Editor
 覚えておきたい (4/4)
 ・ファイル出力やシステムコールも可能
    System.IO.StreamWriterを使ってgmcs.rspを書きだしたり
    System.Diagnostics.Processを使ってシステムコールを
    呼び出すことも可能。Unity組み込みのWWWクラスを使って
    簡単にウェブサーバと連携したり、可能性は無限大。




                                          30/30

More Related Content

What's hot

Nintendo Switch『OCTOPATH TRAVELER』はこうして作られた
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られたNintendo Switch『OCTOPATH TRAVELER』はこうして作られた
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られた
エピック・ゲームズ・ジャパン Epic Games Japan
 
UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)
UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)
UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)
エピック・ゲームズ・ジャパン Epic Games Japan
 
UE4 アセットロード周り-アセット参照調査-
UE4 アセットロード周り-アセット参照調査-UE4 アセットロード周り-アセット参照調査-
UE4 アセットロード周り-アセット参照調査-
com044
 
少人数開発でもクオリティを諦めない - エンジニア視点から見る少人数開発の極意 -
少人数開発でもクオリティを諦めない - エンジニア視点から見る少人数開発の極意 -少人数開発でもクオリティを諦めない - エンジニア視点から見る少人数開発の極意 -
少人数開発でもクオリティを諦めない - エンジニア視点から見る少人数開発の極意 -
historia_Inc
 
UE4で作成するUIと最適化手法
UE4で作成するUIと最適化手法UE4で作成するUIと最適化手法
UE4で作成するUIと最適化手法
エピック・ゲームズ・ジャパン Epic Games Japan
 
多機能ボイチャを簡単に導入する方法
多機能ボイチャを簡単に導入する方法多機能ボイチャを簡単に導入する方法
多機能ボイチャを簡単に導入する方法
Unity Technologies Japan K.K.
 
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
Unity Technologies Japan K.K.
 
『FINAL FANTASY VII REMAKE』におけるプロファイリングと最適化事例 UNREAL FEST EXTREME 2021 SUMMER
『FINAL FANTASY VII REMAKE』におけるプロファイリングと最適化事例 UNREAL FEST EXTREME 2021 SUMMER『FINAL FANTASY VII REMAKE』におけるプロファイリングと最適化事例 UNREAL FEST EXTREME 2021 SUMMER
『FINAL FANTASY VII REMAKE』におけるプロファイリングと最適化事例 UNREAL FEST EXTREME 2021 SUMMER
エピック・ゲームズ・ジャパン Epic Games Japan
 
[CEDEC2018] UE4アニメーションシステム総おさらい
[CEDEC2018] UE4アニメーションシステム総おさらい[CEDEC2018] UE4アニメーションシステム総おさらい
[CEDEC2018] UE4アニメーションシステム総おさらい
エピック・ゲームズ・ジャパン Epic Games Japan
 
日本一詳しい人が教えるUE4
日本一詳しい人が教えるUE4日本一詳しい人が教えるUE4
[4.20版] UE4におけるLoadingとGCのProfilingと最適化手法
[4.20版] UE4におけるLoadingとGCのProfilingと最適化手法[4.20版] UE4におけるLoadingとGCのProfilingと最適化手法
[4.20版] UE4におけるLoadingとGCのProfilingと最適化手法
エピック・ゲームズ・ジャパン Epic Games Japan
 
猫でも分かる UE4の新しいサンプル「Action RPG」について
猫でも分かる UE4の新しいサンプル「Action RPG」について猫でも分かる UE4の新しいサンプル「Action RPG」について
猫でも分かる UE4の新しいサンプル「Action RPG」について
エピック・ゲームズ・ジャパン Epic Games Japan
 
猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について
エピック・ゲームズ・ジャパン Epic Games Japan
 
UE4でAIとビヘイビアツリーと-基礎-
UE4でAIとビヘイビアツリーと-基礎-UE4でAIとビヘイビアツリーと-基礎-
UE4でAIとビヘイビアツリーと-基礎-
com044
 
Unityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTipsUnityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTips
Unity Technologies Japan K.K.
 
60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編
エピック・ゲームズ・ジャパン Epic Games Japan
 
UE4におけるキャラクタークラス設計
UE4におけるキャラクタークラス設計UE4におけるキャラクタークラス設計
UE4におけるキャラクタークラス設計
Masahiko Nakamura
 
UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-
UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-
UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-
Tatsuya Iwama
 
UE4 MultiPlayer Online Deep Dive: 実践編1 (Byking様ご講演) #UE4DD
UE4 MultiPlayer Online Deep Dive: 実践編1 (Byking様ご講演)  #UE4DDUE4 MultiPlayer Online Deep Dive: 実践編1 (Byking様ご講演)  #UE4DD
UE4 MultiPlayer Online Deep Dive: 実践編1 (Byking様ご講演) #UE4DD
エピック・ゲームズ・ジャパン Epic Games Japan
 
UE4を用いたTPS制作事例 EDF:IR レベル構成について
UE4を用いたTPS制作事例 EDF:IR レベル構成についてUE4を用いたTPS制作事例 EDF:IR レベル構成について
UE4を用いたTPS制作事例 EDF:IR レベル構成について
エピック・ゲームズ・ジャパン Epic Games Japan
 

What's hot (20)

Nintendo Switch『OCTOPATH TRAVELER』はこうして作られた
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られたNintendo Switch『OCTOPATH TRAVELER』はこうして作られた
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られた
 
UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)
UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)
UE4 Performance and Profiling | Unreal Dev Day Montreal 2017 (日本語訳)
 
UE4 アセットロード周り-アセット参照調査-
UE4 アセットロード周り-アセット参照調査-UE4 アセットロード周り-アセット参照調査-
UE4 アセットロード周り-アセット参照調査-
 
少人数開発でもクオリティを諦めない - エンジニア視点から見る少人数開発の極意 -
少人数開発でもクオリティを諦めない - エンジニア視点から見る少人数開発の極意 -少人数開発でもクオリティを諦めない - エンジニア視点から見る少人数開発の極意 -
少人数開発でもクオリティを諦めない - エンジニア視点から見る少人数開発の極意 -
 
UE4で作成するUIと最適化手法
UE4で作成するUIと最適化手法UE4で作成するUIと最適化手法
UE4で作成するUIと最適化手法
 
多機能ボイチャを簡単に導入する方法
多機能ボイチャを簡単に導入する方法多機能ボイチャを簡単に導入する方法
多機能ボイチャを簡単に導入する方法
 
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
【CEDEC2017】Unityを使ったNintendo Switch™向けのタイトル開発・移植テクニック!!
 
『FINAL FANTASY VII REMAKE』におけるプロファイリングと最適化事例 UNREAL FEST EXTREME 2021 SUMMER
『FINAL FANTASY VII REMAKE』におけるプロファイリングと最適化事例 UNREAL FEST EXTREME 2021 SUMMER『FINAL FANTASY VII REMAKE』におけるプロファイリングと最適化事例 UNREAL FEST EXTREME 2021 SUMMER
『FINAL FANTASY VII REMAKE』におけるプロファイリングと最適化事例 UNREAL FEST EXTREME 2021 SUMMER
 
[CEDEC2018] UE4アニメーションシステム総おさらい
[CEDEC2018] UE4アニメーションシステム総おさらい[CEDEC2018] UE4アニメーションシステム総おさらい
[CEDEC2018] UE4アニメーションシステム総おさらい
 
日本一詳しい人が教えるUE4
日本一詳しい人が教えるUE4日本一詳しい人が教えるUE4
日本一詳しい人が教えるUE4
 
[4.20版] UE4におけるLoadingとGCのProfilingと最適化手法
[4.20版] UE4におけるLoadingとGCのProfilingと最適化手法[4.20版] UE4におけるLoadingとGCのProfilingと最適化手法
[4.20版] UE4におけるLoadingとGCのProfilingと最適化手法
 
猫でも分かる UE4の新しいサンプル「Action RPG」について
猫でも分かる UE4の新しいサンプル「Action RPG」について猫でも分かる UE4の新しいサンプル「Action RPG」について
猫でも分かる UE4の新しいサンプル「Action RPG」について
 
猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について
 
UE4でAIとビヘイビアツリーと-基礎-
UE4でAIとビヘイビアツリーと-基礎-UE4でAIとビヘイビアツリーと-基礎-
UE4でAIとビヘイビアツリーと-基礎-
 
Unityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTipsUnityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTips
 
60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編60fpsアクションを実現する秘訣を伝授 解析編
60fpsアクションを実現する秘訣を伝授 解析編
 
UE4におけるキャラクタークラス設計
UE4におけるキャラクタークラス設計UE4におけるキャラクタークラス設計
UE4におけるキャラクタークラス設計
 
UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-
UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-
UE4 コリジョン検証 -HitとOverlapイベントが発生する条件について-
 
UE4 MultiPlayer Online Deep Dive: 実践編1 (Byking様ご講演) #UE4DD
UE4 MultiPlayer Online Deep Dive: 実践編1 (Byking様ご講演)  #UE4DDUE4 MultiPlayer Online Deep Dive: 実践編1 (Byking様ご講演)  #UE4DD
UE4 MultiPlayer Online Deep Dive: 実践編1 (Byking様ご講演) #UE4DD
 
UE4を用いたTPS制作事例 EDF:IR レベル構成について
UE4を用いたTPS制作事例 EDF:IR レベル構成についてUE4を用いたTPS制作事例 EDF:IR レベル構成について
UE4を用いたTPS制作事例 EDF:IR レベル構成について
 

Similar to Extending the Unity Editor

Extending the Unity Editor Extended
Extending the Unity Editor ExtendedExtending the Unity Editor Extended
Extending the Unity Editor ExtendedMasamitsu Ishikawa
 
ゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!第11回 エディター拡張してみようゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!
 
iOSのUI構築小技集(小さなとこから始められる編)
iOSのUI構築小技集(小さなとこから始められる編)iOSのUI構築小技集(小さなとこから始められる編)
iOSのUI構築小技集(小さなとこから始められる編)
Fumiya Sakai
 
ARコンテンツ作成勉強会:Myoを用いたVRコンテンツ開発
ARコンテンツ作成勉強会:Myoを用いたVRコンテンツ開発ARコンテンツ作成勉強会:Myoを用いたVRコンテンツ開発
ARコンテンツ作成勉強会:Myoを用いたVRコンテンツ開発
Takashi Yoshinaga
 
Unity勉強会ハンズオン
Unity勉強会ハンズオンUnity勉強会ハンズオン
Unity勉強会ハンズオン
Kodai Yano
 
Unityの夕べ in Fukuoka
Unityの夕べ in FukuokaUnityの夕べ in Fukuoka
Unityの夕べ in Fukuoka
Shinobu Izumi
 
Editor スクリプティング 入門
Editor スクリプティング 入門Editor スクリプティング 入門
Editor スクリプティング 入門
Keigo Ando
 
Flashup 8
Flashup 8Flashup 8
Flashup 8
Katsushi Suzuki
 
【Unite 2018 Tokyo】エディター拡張マニアクス2018
【Unite 2018 Tokyo】エディター拡張マニアクス2018【Unite 2018 Tokyo】エディター拡張マニアクス2018
【Unite 2018 Tokyo】エディター拡張マニアクス2018
Unity Technologies Japan K.K.
 
Pin-point rebuildable and non-rebuild custom widget
Pin-point rebuildable and non-rebuild custom widgetPin-point rebuildable and non-rebuild custom widget
Pin-point rebuildable and non-rebuild custom widget
cch-robo
 
HoloLensハンズオン:AirTap & SpatialMapping編
HoloLensハンズオン:AirTap & SpatialMapping編HoloLensハンズオン:AirTap & SpatialMapping編
HoloLensハンズオン:AirTap & SpatialMapping編
Takashi Yoshinaga
 
OSC2011 Androidハンズオン
OSC2011 AndroidハンズオンOSC2011 Androidハンズオン
OSC2011 Androidハンズオン
Katsumi Honda
 
第10回ゲームツクール uGUIをアニメーションさせよう
第10回ゲームツクール uGUIをアニメーションさせよう第10回ゲームツクール uGUIをアニメーションさせよう
第10回ゲームツクール uGUIをアニメーションさせよう
ゲームツクール!
 
Flutter のリアクティブ戦略 set state 〜 redux まで
Flutter のリアクティブ戦略 set state 〜 redux までFlutter のリアクティブ戦略 set state 〜 redux まで
Flutter のリアクティブ戦略 set state 〜 redux まで
cch-robo
 
2015年度研究室プレ卒研用Android講座2
2015年度研究室プレ卒研用Android講座22015年度研究室プレ卒研用Android講座2
2015年度研究室プレ卒研用Android講座2
Hokuto Tateyama
 
FlutterをRenderObjectまで理解する
FlutterをRenderObjectまで理解するFlutterをRenderObjectまで理解する
FlutterをRenderObjectまで理解する
KeisukeKiriyama
 
デザイナーとエンジニアが話す、iOSアプリケーション開発
デザイナーとエンジニアが話す、iOSアプリケーション開発デザイナーとエンジニアが話す、iOSアプリケーション開発
デザイナーとエンジニアが話す、iOSアプリケーション開発
Kenta Ohsugi
 
試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine
試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine
試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine
Fumiya Sakai
 
20120620 ngui japanese
20120620 ngui japanese20120620 ngui japanese
20120620 ngui japanese
Yasuyuki Kamata
 
UE4 HUD作成
UE4 HUD作成UE4 HUD作成
UE4 HUD作成
Tatsuya Iwama
 

Similar to Extending the Unity Editor (20)

Extending the Unity Editor Extended
Extending the Unity Editor ExtendedExtending the Unity Editor Extended
Extending the Unity Editor Extended
 
ゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!第11回 エディター拡張してみようゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!第11回 エディター拡張してみよう
 
iOSのUI構築小技集(小さなとこから始められる編)
iOSのUI構築小技集(小さなとこから始められる編)iOSのUI構築小技集(小さなとこから始められる編)
iOSのUI構築小技集(小さなとこから始められる編)
 
ARコンテンツ作成勉強会:Myoを用いたVRコンテンツ開発
ARコンテンツ作成勉強会:Myoを用いたVRコンテンツ開発ARコンテンツ作成勉強会:Myoを用いたVRコンテンツ開発
ARコンテンツ作成勉強会:Myoを用いたVRコンテンツ開発
 
Unity勉強会ハンズオン
Unity勉強会ハンズオンUnity勉強会ハンズオン
Unity勉強会ハンズオン
 
Unityの夕べ in Fukuoka
Unityの夕べ in FukuokaUnityの夕べ in Fukuoka
Unityの夕べ in Fukuoka
 
Editor スクリプティング 入門
Editor スクリプティング 入門Editor スクリプティング 入門
Editor スクリプティング 入門
 
Flashup 8
Flashup 8Flashup 8
Flashup 8
 
【Unite 2018 Tokyo】エディター拡張マニアクス2018
【Unite 2018 Tokyo】エディター拡張マニアクス2018【Unite 2018 Tokyo】エディター拡張マニアクス2018
【Unite 2018 Tokyo】エディター拡張マニアクス2018
 
Pin-point rebuildable and non-rebuild custom widget
Pin-point rebuildable and non-rebuild custom widgetPin-point rebuildable and non-rebuild custom widget
Pin-point rebuildable and non-rebuild custom widget
 
HoloLensハンズオン:AirTap & SpatialMapping編
HoloLensハンズオン:AirTap & SpatialMapping編HoloLensハンズオン:AirTap & SpatialMapping編
HoloLensハンズオン:AirTap & SpatialMapping編
 
OSC2011 Androidハンズオン
OSC2011 AndroidハンズオンOSC2011 Androidハンズオン
OSC2011 Androidハンズオン
 
第10回ゲームツクール uGUIをアニメーションさせよう
第10回ゲームツクール uGUIをアニメーションさせよう第10回ゲームツクール uGUIをアニメーションさせよう
第10回ゲームツクール uGUIをアニメーションさせよう
 
Flutter のリアクティブ戦略 set state 〜 redux まで
Flutter のリアクティブ戦略 set state 〜 redux までFlutter のリアクティブ戦略 set state 〜 redux まで
Flutter のリアクティブ戦略 set state 〜 redux まで
 
2015年度研究室プレ卒研用Android講座2
2015年度研究室プレ卒研用Android講座22015年度研究室プレ卒研用Android講座2
2015年度研究室プレ卒研用Android講座2
 
FlutterをRenderObjectまで理解する
FlutterをRenderObjectまで理解するFlutterをRenderObjectまで理解する
FlutterをRenderObjectまで理解する
 
デザイナーとエンジニアが話す、iOSアプリケーション開発
デザイナーとエンジニアが話す、iOSアプリケーション開発デザイナーとエンジニアが話す、iOSアプリケーション開発
デザイナーとエンジニアが話す、iOSアプリケーション開発
 
試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine
試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine
試して感覚を掴んでみるUICollectionViewCompositionalLayout & Combine
 
20120620 ngui japanese
20120620 ngui japanese20120620 ngui japanese
20120620 ngui japanese
 
UE4 HUD作成
UE4 HUD作成UE4 HUD作成
UE4 HUD作成
 

Extending the Unity Editor

  • 1. Extending the Unity Editor Unity Editor の 拡張について
  • 2. Extending the Unity Editor まずはUnityのGUIを理解しよう (1/2) ・基本的にデバッグ用 毎フレーム1つ1つのコンポーネントについて判定・再描画が 行われるので重い。また使いこなすにはGUISkinなどの細かい 仕様を覚えなくてはならず面倒。 ・Viewport空間ではなくScreen空間に描画 スクリーンに対する絶対座標で描画されるので、画面解像度が 変わった時に破綻する。 ・フォントの問題 PC/Mac以外で日本語文字を表示しようとすると非常に面倒。 携帯機ではDynamicフォントが使えない。 2/30
  • 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. 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. 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. 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. Extending the Unity Editor EditorGUIとEditorGUILayout (2/2) ・基本的にEditorGUILayoutを使用 ゲーム用のGUIがゲーム画面の左上を基準にして配置されるよ うに、エディタ用のGUIはインスペクタやウィンドウの左上を 基準にして配置されていく。 座標を全部自前で計算してもいいが、EditorGUILayoutで配置 しておくとスケーリングが自動で行われるのでスマート。 ・位置調整用のパーツもある 領域のサイズを考慮して自動的に伸縮するFlexibleSpace()や 逆に勝手に伸縮しないようにするGUILayout.ExpandWidth() を上手く使ってかっこ良く配置しよう。 7/30
  • 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. Extending the Unity Editor インスペクタを拡張してみよう (2/5) ・どう拡張できるの? 例えば左のようなプロパティを持つコンポーネントを作ったと する。するとインスペクタでの表示は右のようになる。 using UnityEngine; public class Hoge : MonoBehaviour { public Vector3 velocity; } これではVectorの各要素が縦に並んでいて非常に無様である。 しかも初期状態では折りたたまれているし、色々ひどい。 これをTransformの表示のように横に並べたい。 すっきり! 9/30
  • 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. 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. Extending the Unity Editor インスペクタを拡張してみよう (5/5) ・拡張エディタクラスを堪能する Unityにフォーカスを戻してコンパイルエラーなどがなければ、 インスペクタの表示が以下のように変化している。  Undo.RegisterUndo()して  あるので、Ctrl+Zで取り消し、  Ctrl+Yでやり直しもバッチリ。 12/30
  • 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. Extending the Unity Editor もっと拡張してみよう (2/2) ・挙動の確認 Unityにフォーカスを戻してコンパイルエラーなどがなければ、 インスペクタの表示が以下のように変化している。  EditorStylesの指定や空白を  配置したことで、まとまりの  ある見た目にする事ができた。 14/30
  • 15. Extending the Unity Editor 他にもこんな便利なパーツが ・範囲指定 EditorGUILayout.MinMaxSlider() ・ゲージ表示 EditorGUI.ProgressBar() 15/30
  • 16. Extending the Unity Editor 拡張インスペクタの振る舞い (1/2) ・必要な時にnewされている 先ほど実装した拡張インスペクタは、Unityエディタ上で対象の コンポーネントがアタッチされているオブジェクトが選択され る度にnewされている。 従って、1つのオブジェクトを選択している間はインスペクタ 自体のメンバプロパティは保持されるが、別のオブジェクトを 選択するとインスペクタのメンバは初期値に戻る。 複数オブジェクトをまたいでやりとりしたい情報がある場合は staticメンバを利用しよう。 またOnEnable()をオーバーライドすることで、オブジェクト を選択した瞬間の挙動を定義することも可能。 16/30
  • 17. Extending the Unity Editor 拡張インスペクタの振る舞い (2/2) ・必要な時にOnInspectorGUI()が呼ばれる OnGUI()が毎フレーム呼ばれるのと違い、OnInspectorGUI() はインスペクターペインの再描画が必要になったタイミングで 随時呼ばれている。 従って「一定間隔で明滅する」といったような、エディタ上で リアルタイムに何かを動かすような処理は基本的にできない。 (毎回Repaint()を呼びまくれば可能ではある) ・シーンビューの更新時にはOnSceneGUI() インスペクタの親クラスであるEditorにはOnSceneGUI()と いうメソッドもあり、これはシーンビューが更新されるときに 呼ばれている。どう使うのかというと… 17/30
  • 18. Extending the Unity Editor シーンビューも拡張してみよう (1/3) ・ハンドル(マニピュレータ)の表示 ベクトルを下図のようにグラフィカルに表示したい。 18/30
  • 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. Extending the Unity Editor シーンビューも拡張してみよう (3/3) ・ハンドル(マニピュレータ)の表示 ベクトルがグラフィカルに表示されるようになった。 20/30
  • 21. Extending the Unity Editor 拡張インスペクタの例 21/30
  • 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. 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. 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. 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. Extending the Unity Editor ウィンドウを作ってみよう (5/5) ・ウィンドウが完成 選択中のゲームオブジェクト全てのマテリアルを、指定した ものに差し替えるツールが完成。 マテリアルを選択し、差し替え たいオブジェクトを選択状態に したらReplaceボタンを押す 選択中のオブジェクトにレンダラが付い ていれば、そのマテリアルが差し替わる 26/30
  • 27. Extending the Unity Editor 覚えておきたい (1/4) ・Selectionクラス エディタ上で選択中のオブジェクトには、Selectionクラスを 通してアクセスできる。 27/30
  • 28. Extending the Unity Editor 覚えておきたい (2/4) ・Undoクラス スクリプトから変更した情報は、何もしないとUndoの履歴に 残らない。エディタの拡張をする場合はUndo.RegisterUndo を有効に使い、ユーザーの利便性を図ろう。 28/30
  • 29. Extending the Unity Editor 覚えておきたい (3/4) ・EditorUtility、FileUtilなどのユーティリティ EditorUtilityにはファイルオープンダイアログやYes/No形式 のダイアログを表示するためのメソッド、FileUtilにはファイル のコピーや削除などを行うメソッドなど、色々便利なインター フェースが用意されている。 ・スクリプトから全ての設定にアクセス可能 PlayerSettingsやEditorUserBuildSettingsなどを通して、 エディタ上で触れる設定項目は全てスクリプトからも操作が 可能。面倒な処理はバッチ化してしまえ。 29/30
  • 30. Extending the Unity Editor 覚えておきたい (4/4) ・ファイル出力やシステムコールも可能 System.IO.StreamWriterを使ってgmcs.rspを書きだしたり System.Diagnostics.Processを使ってシステムコールを 呼び出すことも可能。Unity組み込みのWWWクラスを使って 簡単にウェブサーバと連携したり、可能性は無限大。 30/30