6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PONOSAdvent Calendar 2021

Day 9

Unityエディタの中を見て理解を深める

Last updated at Posted at 2021-12-08

PONOS Advent Calendar 2021の9日目の記事です。

昨日は@nissy_gpさんの「YouTubeの英語の動画はどう見たほうが間違えないのか」でした。

はじめに

先日、「Debug.Log()の全文をファイル出力し、で省略された内容をすぐに確認できるようにする」という記事を投稿しました。
この調査を進める中でUnityエディタ内のクラスにアクセスする機会があり、やり方について知っておくとエディタを拡張する際に便利かと思いましたので、共有いたします。

確認環境はUnity 2019.4.32f1です。

Unityエディタの中を見る方法

通常、Unityエディタ内で使用されているクラス(例えば、Consoleを始めとした各ウインドウの制御など)は、利用することができません。
ですが、クラスの定義が判明していれば、C#のリフレクションの機能を使ってクラスを利用することができます。

では、Unityエディタ内のクラスの定義はどこで確認したら良いでしょうか。
実はUnity公式から実際に運用されているC#のコードが公開されています。
(確認する際は、自身が使用しているUnityのバージョンに合わせてブランチまたはタグを切り替えてください)
GitHub - Unity-Technologies/UnityCsReference: Unity C# reference source code.

ライセンスは以下が適用されています。(対象コードは参照にのみ利用できます)
Unity Reference-Only License (“License”) - Unity

このリポジトリのコードを読むことで、Unityエディタ内にどういったクラスが定義されているのかを知ることができます。

サンプル

さて、ではUnityエディタ内のクラスを利用するサンプルとして、**「Consoleウインドウのフィルター欄に『PONOS』文字列を設定する」**機能を実装してみます。

型を取得する

まずは、リフレクションの処理を用いてConsoleWindowの型を取得してみましょう。

Consoleウインドウの処理はConsolwWindowクラスに実装されています。
UnityCsReference/ConsoleWindow.cs at 2019.4 · Unity-Technologies/UnityCsReference · GitHub

System.Refrection.Assemblyクラスを利用してConsoleWindowが含まれるエディタ用のアセンブリオブジェクトを取得し、その中から対象となる型情報を取得しています。

// エディタ用のアセンブリを取得。
var assembly = typeof(Editor).Assembly;

// Consoleウインドウの型情報を取得。
var consoleWindowType = assembly.GetType("UnityEditor.ConsoleWindow");

メソッド情報を取得する

次に、フィルター欄に文字列を設定するためのメソッドConsoleWindow.SetFilter()を実行するために必要な、メソッド情報MethodInfoを探します。
メソッド情報を探すときは対象のメソッド名が必要となります。

また、対象となるメソッドの定義に応じて、適切にBindingFlagsで検索方法を指定する必要があります。
今回対象となるSetFilter()メソッドは以下のように定義されているため、BindingFlagsBindingFlags.Instance | BindingFlags.NonPublicを指定します。

private void SetFilter(string filteringText)

※その他のBindingFlagsの値は以下を参考にしてください。
BindingFlags 列挙型 (System.Reflection) | Microsoft Docs

以上を踏まえて、メソッド情報を取得するためのコードは以下のようになります。

// SetFilter()メソッドの情報を取得する。
// フラグとして「インスタンスメンバである」「パブリックアクセス以外のメンバを含める」を渡しておく。
var bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
var setFilterMethodInfo = consoleWindowType.GetMethod("SetFilter", bindingAttr);

メソッドを実行する

最後にメソッド情報を元に、処理を実行します。
MethodInfoから処理を実行する際は、「メソッドを実行させるオブジェクト」を渡す必要があります。
ConsoleWindowオブジェクトはEditorApplication.GetWindow()から取得が可能です。

// メソッドの実行対象となるConsoleウインドウのオブジェクトを取得。
var consoleWindow = EditorWindow.GetWindow(consoleWindowType);

// メソッド情報を元に、対象のオブジェクトに対してメソッドを実行する。
setFilterMethodInfo.Invoke(consoleWindow, new object[] { "PONOS" });

コード全文

説明は以上です。コードの全文は以下のようになります。

using System.Reflection;
using UnityEditor;

/// <summary>
/// Consoleウインドウのフィルター欄に文字列を設定するクラス。
/// </summary>
public static class ConsoleFilterSetter
{
    /// <summary>
    /// Consoleウインドウのフィルター欄に「PONOS」を設定する。
    /// </summary>
    [MenuItem("Console Filter/Set \"PONOS\"")]
    public static void SetPONOS()
    {
        // エディタ用のアセンブリを取得。
        var assembly = typeof(Editor).Assembly;

        // Consoleウインドウの型情報を取得。
        var consoleWindowType = assembly.GetType("UnityEditor.ConsoleWindow");

        // SetFilter()メソッドの情報を取得する。
        // フラグとして「インスタンスメソッド」「パブリックでない」を渡しておく。
        var bindingAttr = BindingFlags.Instance | BindingFlags.NonPublic;
        var setFilterMethodInfo = consoleWindowType.GetMethod("SetFilter", bindingAttr);

        // メソッドの実行対象となるConsoleウインドウのオブジェクトを取得。
        var consoleWindow = EditorWindow.GetWindow(consoleWindowType);

        // メソッド情報を元に、対象のオブジェクトに対してメソッドを実行する。
        setFilterMethodInfo.Invoke(consoleWindow, new object[] { "PONOS" });
    }
}

実行結果は以下です。

PONOS動画.gif

まとめ

UnityCsReferenceリポジトリを見ることでUnityエディタ内の処理を追うことができるので、Unityに対する理解を一層深めることができると思います!

明日は@nisei275さんです!

6
3
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
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?