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 (20)

UE4ローカライズ事例 (UE4 Localization Deep Dive)
UE4ローカライズ事例 (UE4 Localization Deep Dive)UE4ローカライズ事例 (UE4 Localization Deep Dive)
UE4ローカライズ事例 (UE4 Localization Deep Dive)
エピック・ゲームズ・ジャパン Epic Games Japan
 
[CEDEC2017] UE4プロファイリングツール総おさらい(グラフィクス編)
[CEDEC2017] UE4プロファイリングツール総おさらい(グラフィクス編)[CEDEC2017] UE4プロファイリングツール総おさらい(グラフィクス編)
[CEDEC2017] UE4プロファイリングツール総おさらい(グラフィクス編)
エピック・ゲームズ・ジャパン Epic Games Japan
 
[CEDEC2018] UE4アニメーションシステム総おさらい
[CEDEC2018] UE4アニメーションシステム総おさらい[CEDEC2018] UE4アニメーションシステム総おさらい
[CEDEC2018] UE4アニメーションシステム総おさらい
エピック・ゲームズ・ジャパン Epic Games Japan
 
UE5制作事例 “The Market of Light” ~Nanite/Lumenへの挑戦~
UE5制作事例 “The Market of Light” ~Nanite/Lumenへの挑戦~UE5制作事例 “The Market of Light” ~Nanite/Lumenへの挑戦~
UE5制作事例 “The Market of Light” ~Nanite/Lumenへの挑戦~
historia_Inc
 
「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像
「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像
「Press Button, Drink Coffee」 UE4における ビルドパイプラインとメンテナンスの全体像
エピック・ゲームズ・ジャパン Epic Games Japan
 
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック
エピック・ゲームズ・ジャパン Epic Games Japan
 
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でマルチプレイヤーゲームを作ろう
UE4でマルチプレイヤーゲームを作ろうUE4でマルチプレイヤーゲームを作ろう
UE4でマルチプレイヤーゲームを作ろう
エピック・ゲームズ・ジャパン Epic Games Japan
 
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメントヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
historia_Inc
 
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
UnityTechnologiesJapan002
 
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
Unity Technologies Japan K.K.
 
UE4のローカライズ機能紹介 (UE4 Localization Deep Dive)
UE4のローカライズ機能紹介 (UE4 Localization Deep Dive)UE4のローカライズ機能紹介 (UE4 Localization Deep Dive)
UE4のローカライズ機能紹介 (UE4 Localization Deep Dive)
エピック・ゲームズ・ジャパン Epic Games Japan
 
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTERUE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
エピック・ゲームズ・ジャパン Epic Games Japan
 
CEDEC 2020 - 高品質かつ低負荷な3Dライブを実現するシェーダー開発 ~『ラブライブ!スクールアイドルフェスティバル ALL STARS』(スク...
CEDEC 2020 - 高品質かつ低負荷な3Dライブを実現するシェーダー開発 ~『ラブライブ!スクールアイドルフェスティバル ALL STARS』(スク...CEDEC 2020 - 高品質かつ低負荷な3Dライブを実現するシェーダー開発 ~『ラブライブ!スクールアイドルフェスティバル ALL STARS』(スク...
CEDEC 2020 - 高品質かつ低負荷な3Dライブを実現するシェーダー開発 ~『ラブライブ!スクールアイドルフェスティバル ALL STARS』(スク...
KLab Inc. / Tech
 
UnrealBuildTool勉強会まとめ
UnrealBuildTool勉強会まとめUnrealBuildTool勉強会まとめ
UnrealBuildTool勉強会まとめ
Shun Sasaki
 
UE4におけるレベル制作事例
UE4におけるレベル制作事例  UE4におけるレベル制作事例
UE4におけるレベル制作事例
エピック・ゲームズ・ジャパン Epic Games Japan
 
[GTMF2019] Python / BlueprintによるUnreal Engineの自動化
[GTMF2019] Python / BlueprintによるUnreal Engineの自動化[GTMF2019] Python / BlueprintによるUnreal Engineの自動化
[GTMF2019] Python / BlueprintによるUnreal Engineの自動化
エピック・ゲームズ・ジャパン Epic Games Japan
 
Editor Utility Widgetで色々便利にしてみた。
Editor Utility Widgetで色々便利にしてみた。Editor Utility Widgetで色々便利にしてみた。
Editor Utility Widgetで色々便利にしてみた。
IndieusGames
 
[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]自動テストでもっと楽したい!
[UE4]自動テストでもっと楽したい![UE4]自動テストでもっと楽したい!
[UE4]自動テストでもっと楽したい!
com044
 
UE5制作事例 “The Market of Light” ~Nanite/Lumenへの挑戦~
UE5制作事例 “The Market of Light” ~Nanite/Lumenへの挑戦~UE5制作事例 “The Market of Light” ~Nanite/Lumenへの挑戦~
UE5制作事例 “The Market of Light” ~Nanite/Lumenへの挑戦~
historia_Inc
 
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメントヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
historia_Inc
 
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
【Unite Tokyo 2019】Unityだったら簡単!マルチプレイ用ゲームサーバ開発 ~実践編~
UnityTechnologiesJapan002
 
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
Unity Technologies Japan K.K.
 
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTERUE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
エピック・ゲームズ・ジャパン Epic Games Japan
 
CEDEC 2020 - 高品質かつ低負荷な3Dライブを実現するシェーダー開発 ~『ラブライブ!スクールアイドルフェスティバル ALL STARS』(スク...
CEDEC 2020 - 高品質かつ低負荷な3Dライブを実現するシェーダー開発 ~『ラブライブ!スクールアイドルフェスティバル ALL STARS』(スク...CEDEC 2020 - 高品質かつ低負荷な3Dライブを実現するシェーダー開発 ~『ラブライブ!スクールアイドルフェスティバル ALL STARS』(スク...
CEDEC 2020 - 高品質かつ低負荷な3Dライブを実現するシェーダー開発 ~『ラブライブ!スクールアイドルフェスティバル ALL STARS』(スク...
KLab Inc. / Tech
 
UnrealBuildTool勉強会まとめ
UnrealBuildTool勉強会まとめUnrealBuildTool勉強会まとめ
UnrealBuildTool勉強会まとめ
Shun Sasaki
 
Editor Utility Widgetで色々便利にしてみた。
Editor Utility Widgetで色々便利にしてみた。Editor Utility Widgetで色々便利にしてみた。
Editor Utility Widgetで色々便利にしてみた。
IndieusGames
 
[UE4]自動テストでもっと楽したい!
[UE4]自動テストでもっと楽したい![UE4]自動テストでもっと楽したい!
[UE4]自動テストでもっと楽したい!
com044
 

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
Masamitsu Ishikawa
 
ゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!第11回 エディター拡張してみようゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!
 
Unity エディタ拡張
Unity エディタ拡張Unity エディタ拡張
Unity エディタ拡張
Shota Baba
 
知って得するUnity エディタ拡張編
知って得するUnity エディタ拡張編知って得するUnity エディタ拡張編
知って得するUnity エディタ拡張編
Shota Baba
 
【Unite 2018 Tokyo】エディター拡張マニアクス2018
【Unite 2018 Tokyo】エディター拡張マニアクス2018【Unite 2018 Tokyo】エディター拡張マニアクス2018
【Unite 2018 Tokyo】エディター拡張マニアクス2018
Unity Technologies Japan K.K.
 
Unityの夕べ in Fukuoka
Unityの夕べ in FukuokaUnityの夕べ in Fukuoka
Unityの夕べ in Fukuoka
Shinobu Izumi
 
Kuug 第1回
Kuug 第1回Kuug 第1回
Kuug 第1回
Shinobu Izumi
 
UnityLecture @Kyushu University
UnityLecture @Kyushu UniversityUnityLecture @Kyushu University
UnityLecture @Kyushu University
Kosuke Kaneko
 
Unite2015 uGUIの拡張と応用
Unite2015 uGUIの拡張と応用Unite2015 uGUIの拡張と応用
Unite2015 uGUIの拡張と応用
Ryohei Tokimura
 
2018/01/17 第3回 HoloLens 参考書読み会発表資料
2018/01/17 第3回 HoloLens 参考書読み会発表資料2018/01/17 第3回 HoloLens 参考書読み会発表資料
2018/01/17 第3回 HoloLens 参考書読み会発表資料
Yusuke Furuta
 
俺はただ、ボタンを手で置きたくないだけなんだ 170512平山尚
俺はただ、ボタンを手で置きたくないだけなんだ 170512平山尚俺はただ、ボタンを手で置きたくないだけなんだ 170512平山尚
俺はただ、ボタンを手で置きたくないだけなんだ 170512平山尚
Takashi Hirayama
 
Editor スクリプティング 入門
Editor スクリプティング 入門Editor スクリプティング 入門
Editor スクリプティング 入門
Keigo Ando
 
Unity勉強会ハンズオン
Unity勉強会ハンズオンUnity勉強会ハンズオン
Unity勉強会ハンズオン
Kodai Yano
 
UnityとBlenderハンズオン第1章
UnityとBlenderハンズオン第1章UnityとBlenderハンズオン第1章
UnityとBlenderハンズオン第1章
yaju88
 
Unityで横スクロールアクションゲームを作ってみる(第2回unity初心者勉強会)
Unityで横スクロールアクションゲームを作ってみる(第2回unity初心者勉強会)Unityで横スクロールアクションゲームを作ってみる(第2回unity初心者勉強会)
Unityで横スクロールアクションゲームを作ってみる(第2回unity初心者勉強会)
Makoto Yamahira
 
実行時のために最適なデータ構造を作成しよう
実行時のために最適なデータ構造を作成しよう実行時のために最適なデータ構造を作成しよう
実行時のために最適なデータ構造を作成しよう
Hiroki Omae
 
UnityでC#を勉強しはじめた私の主張
UnityでC#を勉強しはじめた私の主張UnityでC#を勉強しはじめた私の主張
UnityでC#を勉強しはじめた私の主張
Ryota Murohoshi
 
[崇城大学][熊本Apps!] 学生のためのUnity勉強会
[崇城大学][熊本Apps!] 学生のためのUnity勉強会[崇城大学][熊本Apps!] 学生のためのUnity勉強会
[崇城大学][熊本Apps!] 学生のためのUnity勉強会
Shinobu Izumi
 
Unity3.5と4.0の違い
Unity3.5と4.0の違いUnity3.5と4.0の違い
Unity3.5と4.0の違い
Keigo Ando
 
Extending the Unity Editor Extended
Extending the Unity Editor ExtendedExtending the Unity Editor Extended
Extending the Unity Editor Extended
Masamitsu Ishikawa
 
ゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!第11回 エディター拡張してみようゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!第11回 エディター拡張してみよう
ゲームツクール!
 
Unity エディタ拡張
Unity エディタ拡張Unity エディタ拡張
Unity エディタ拡張
Shota Baba
 
知って得するUnity エディタ拡張編
知って得するUnity エディタ拡張編知って得するUnity エディタ拡張編
知って得するUnity エディタ拡張編
Shota Baba
 
【Unite 2018 Tokyo】エディター拡張マニアクス2018
【Unite 2018 Tokyo】エディター拡張マニアクス2018【Unite 2018 Tokyo】エディター拡張マニアクス2018
【Unite 2018 Tokyo】エディター拡張マニアクス2018
Unity Technologies Japan K.K.
 
Unityの夕べ in Fukuoka
Unityの夕べ in FukuokaUnityの夕べ in Fukuoka
Unityの夕べ in Fukuoka
Shinobu Izumi
 
UnityLecture @Kyushu University
UnityLecture @Kyushu UniversityUnityLecture @Kyushu University
UnityLecture @Kyushu University
Kosuke Kaneko
 
Unite2015 uGUIの拡張と応用
Unite2015 uGUIの拡張と応用Unite2015 uGUIの拡張と応用
Unite2015 uGUIの拡張と応用
Ryohei Tokimura
 
2018/01/17 第3回 HoloLens 参考書読み会発表資料
2018/01/17 第3回 HoloLens 参考書読み会発表資料2018/01/17 第3回 HoloLens 参考書読み会発表資料
2018/01/17 第3回 HoloLens 参考書読み会発表資料
Yusuke Furuta
 
俺はただ、ボタンを手で置きたくないだけなんだ 170512平山尚
俺はただ、ボタンを手で置きたくないだけなんだ 170512平山尚俺はただ、ボタンを手で置きたくないだけなんだ 170512平山尚
俺はただ、ボタンを手で置きたくないだけなんだ 170512平山尚
Takashi Hirayama
 
Editor スクリプティング 入門
Editor スクリプティング 入門Editor スクリプティング 入門
Editor スクリプティング 入門
Keigo Ando
 
Unity勉強会ハンズオン
Unity勉強会ハンズオンUnity勉強会ハンズオン
Unity勉強会ハンズオン
Kodai Yano
 
UnityとBlenderハンズオン第1章
UnityとBlenderハンズオン第1章UnityとBlenderハンズオン第1章
UnityとBlenderハンズオン第1章
yaju88
 
Unityで横スクロールアクションゲームを作ってみる(第2回unity初心者勉強会)
Unityで横スクロールアクションゲームを作ってみる(第2回unity初心者勉強会)Unityで横スクロールアクションゲームを作ってみる(第2回unity初心者勉強会)
Unityで横スクロールアクションゲームを作ってみる(第2回unity初心者勉強会)
Makoto Yamahira
 
実行時のために最適なデータ構造を作成しよう
実行時のために最適なデータ構造を作成しよう実行時のために最適なデータ構造を作成しよう
実行時のために最適なデータ構造を作成しよう
Hiroki Omae
 
UnityでC#を勉強しはじめた私の主張
UnityでC#を勉強しはじめた私の主張UnityでC#を勉強しはじめた私の主張
UnityでC#を勉強しはじめた私の主張
Ryota Murohoshi
 
[崇城大学][熊本Apps!] 学生のためのUnity勉強会
[崇城大学][熊本Apps!] 学生のためのUnity勉強会[崇城大学][熊本Apps!] 学生のためのUnity勉強会
[崇城大学][熊本Apps!] 学生のためのUnity勉強会
Shinobu Izumi
 
Unity3.5と4.0の違い
Unity3.5と4.0の違いUnity3.5と4.0の違い
Unity3.5と4.0の違い
Keigo Ando
 
Ad

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