LoginSignup
2
4

More than 5 years have passed since last update.

【Unity】【エディタ拡張】Editorを継承したクラスを参照する

Last updated at Posted at 2017-06-17

概要

 Unityで他のクラスの参照を得る場合、MonoBehaviour.GetComponent を使うのは周知かと思います。
しかし、エディタ拡張で使う Editor を継承した場合など、MonoBehaviour に紐づかないクラスに対しては、GetComponentは使えません。
 Editor(および EditorWindow)では、ScriptableObject.CreateInstance (公式ドキュメント参考:https://docs.unity3d.com/jp/current/ScriptReference/ScriptableObject.CreateInstance.html)
を使うことで実現できます。

Unityにおける標準的な機能と参照の取得

 Unityで使われるスクリプトのほとんどは、 MonoBehaviour を継承しています。
Monobehavior.png
Start()やUpdate()、コルーチンなどのUnityの標準的な機能は全てこの MonoBehaviour の機能であり、GetComponentもそのうちの一つです。
 そのため、MonoBehaviourを継承しているクラスでは、 GetComponent によって参照が実現できます。

MonoBehaviour を継承しない場合の参照の取得

 当然、MonoBehaviour を継承しない場合、GetComponent は使えません。
とはいえUnityの実装はC#なので、C#的にインスタンスを生成すれば、参照できます。
以下は、エディタ拡張で作ったウィンドウのボタンを押したときに参照したクラスの持つstringの中身をコンソールに書き出すというものです。

Example.cs
public class Example : EditorWindow {

        // MonoBehaviourもなにも継承していないただのクラス
    class InstanceTest
    {
        public string text = "Done";
    }


    [MenuItem("Tools/Example")]
    static void Open()
    {
        EditorWindow.GetWindow<Example>("Example");
    }

    private void OnGUI()
    {
        if(GUILayout.Button("Test"))
        {
                        // クラスのインスタンスを生成
            InstanceTest instance = new InstanceTest();
            Debug.Log(instance.text);
        }
    }
}

上のコードの実行結果は以下になります。

InstanceTest.png

普通ですね。

Editorを継承したクラスを参照する

 Editorで継承したクラスに対して、上と同じようにC#的に参照してみるとどうなるでしょうか。
まず、Editorを継承したクラスHoge.csを用意します。

Hoge.cs
using UnityEngine;
using UnityEditor;

public class Hoge : Editor {

    public void HogeHoge()
    {
        Debug.Log("Hoge");
    }
}

次に、ボタンを押したときに Hoge.cs の HogeHoge() を実行する Example.cs を用意します。

Example.cs
using UnityEngine;
using UnityEditor;

public class Example : EditorWindow {

    [MenuItem("Tools/Example")]
    static void Open()
    {
        EditorWindow.GetWindow<Example>("Example");
    }

    private void OnGUI()
    {
        if(GUILayout.Button("GetComponent"))
        {
            Hoge hoge = new Hoge();
            hoge.HogeHoge();
        }
    }
}

実行結果は以下になります。

6be6bfc3664d997791ed292817e965ae.gif

やりたいことはできていますが、何か怒られますね。内容的には
「ScriptableObject経由でインスタンス生成しろよバカ野郎」
といったところでしょうか。
 実はこれは MonoBehaviour を継承したクラスに対して行っても同じようなことが起こります。
Unityでは非推奨ということですね。具体的に何がまずいのかは調査中ですが怒られないに越したことは無いので、Unityの想定しているやり方に直しましょう。
 Editor や EditorWindow といったクラスは、これまたScriptableObjectを継承しています。

EditorPreviwe.png

ScriptableObject には CreateInstanceという、MonoBehaviour の GetComponent 同様の機能がありますので、そちらを使って先ほどのコードを修正します。

Example.cs
using UnityEngine;
using UnityEditor;

public class Example : EditorWindow {

    [MenuItem("Tools/Example")]
    static void Open()
    {
        EditorWindow.GetWindow<Example>("Example");
    }

    private void OnGUI()
    {
        if(GUILayout.Button("GetComponent"))
        {
            Hoge hoge = ScriptableObject.CreateInstance<Hoge>();
            hoge.HogeHoge();
        }
    }
}

使い方も GetComponent と同じですね。
実行結果は以下になります

cfa8b4d4e4928c0421afe88736df7210.gif

エラーもなく無事に実行できましたね。
それでは快適なエディタ拡張ライフを!

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4