【Unity】エディタ拡張の作り方!サンプル付きで便利な拡張機能の作り方を教えます

Unity エディタ拡張の作り方 ゲーム開発

今回はUnityのエディタ拡張に関するUnity中級者向けの話題で

エディタ拡張の基本的な作り方

をサンプル付きで丁寧にまとめてみるという内容になっております。

Unityでゲームを作っていると、誰しも「Unityエディタ上でこういうことができたら便利なのに、そういう機能がないんだよな…」と思うことがあることでしょう。ですが実はUnityはとても拡張性に優れており、自分で独自の機能を追加できることはご存じでしょうか?

そこでここでは「まだエディタ拡張を作ったことがないけど興味があるよ」という方向けにエディタ拡張の基本的な作り方をご紹介していきますね。

エディタ拡張の基礎知識

そもそもエディタ拡張とは?

まず、そもそもエディタ拡張とは何でしょうか?これはその名の通りUnityエディタの機能を拡張して新しい機能を追加することを指します。

自分でエディタ拡張を作ることができれば、例えば

  • 指定したフォルダ内のテクスチャの最大サイズを一括で変更する
  • あるアセットがどのシーンから参照されているかを検索し、参照を一覧表示する
  • ゲームのローカライズに必要な文字だけを一括抽出し、必要な文字だけをTextMeshProのフォントアセットに含めるようにする

といった手作業では面倒または不可能な作業を自動化することができてとても便利です。

プロジェクトによっては既成のアセットでは対応しきれない作業があったり、いちいちアセットにお金をかけるのは嫌だなと思うことがあったりしますよね。自分でエディタ拡張を作れるようになっておくとこのような場合にもゲーム開発がとても捗りますし、コスト削減にもつながるのでまさに一石二鳥です。

エディタ拡張予備知識

さてそんなエディタ拡張ですが、普通にゲームを作る場合とは少し違う独特なルールがいくつかあるのでそれについてご説明しておきます。

  • エディタ拡張用のC#スクリプトは「Editor」フォルダ内に入れる
  • スクリプトの冒頭に「using UnityEditor」を書いておく
  • ウィンドウを作る場合は「EditorWindow」クラスを継承する

エディタ拡張用のC#スクリプトは「Editor」フォルダ内に入れる

まず一つ目のルールは、エディタ拡張用のC#スクリプトは「Editor」という名前のフォルダ内に入れることです。Editorフォルダにスクリプトを入れることでエディタ拡張として認識されてUnityエディタ上でその機能を使えるようになります。また、Editorフォルダ内のスクリプト等はビルドに含まれることがありません。

なおEditorフォルダは自分で好きな場所に作ってOKなので、もしエディタ拡張を複数作る場合は分かりやすいフォルダ構成にしておきましょう。

スクリプトの冒頭に「using UnityEditor」を書いておく

次にエディタ拡張を作る際は「UnityEditor」という名前空間にあるクラスなどを使うことになるので、スクリプトの冒頭に

using UnityEditor;

と書いておいてください。

ウィンドウを作る場合は「EditorWindow」クラスを継承する

最後に三つ目として、ウィンドウを作る場合は「EditorWindow」クラスを継承する必要があります。

単純なエディタ拡張では専用のウィンドウを一つ作ってそこにUIを並べていく形になるのですが、このときEditorWindowクラスを継承するとUnityエディタにドッキングできるウィンドウをすごく簡単に生成することができます(※具体的なコードはこの後掲載します)。

Unityのエディタ拡張の基本的な作り方

では基本的な部分を頭に入れておいていただいたところで、ここから本題であるエディタ拡張の作り方を実際に動くサンプル付きで解説していきます。

今回作るエディタ拡張のサンプル(指定したフォルダ内のテクスチャの最大サイズを一括で変更するエディタ拡張)

はじめに今回作るエディタ拡張のサンプルコードを掲載すると次のとおりです。

注意事項:

  • 実際に下記のエディタ拡張を試す場合は自己責任でお願いします。Unity2022.3で動作確認をしてありますが他のバージョンで正常に動くかどうかは確認してません。何かあっても私は責任を取らないのでそのつもりで…。
  • 下記のエディタ拡張は個人で使う分には自由に使っていただいて構いませんが再配布などはしないようにしてくださいね。
using UnityEngine;
using UnityEditor;
using System.Linq;

namespace KurokumaSoft
{

	public sealed class TextureSizeChanger : EditorWindow
	{

		readonly int[] sizeOptions = { 32, 64, 128, 256, 512, 1024, 2048, 4096 }; // 最大サイズの選択肢
		
		int selectedSizeIndex = 5; // デフォルトで1024を選択
		string path = string.Empty;
		string folderPath = string.Empty;

		[MenuItem("Tools/KurokumaSoft/Change Texture Max Size")]
		public static void ShowWindow()
		{
			GetWindow<TextureSizeChanger>("Change Texture Max Size");
		}

		void OnGUI()
		{
			GUILayout.Label("Change Max Size of Textures", EditorStyles.boldLabel);
			GUILayout.Space(10);

			if(GUILayout.Button("Select Folder"))
			{
				path = EditorUtility.OpenFolderPanel("Select Folder", "Assets", "");
			}

			if (!string.IsNullOrEmpty(path))
			{
				folderPath = path.Replace(Application.dataPath, "Assets");
				GUILayout.Label("Selected Folder:\n" + folderPath);
				GUILayout.Space(20);
			}

			selectedSizeIndex = EditorGUILayout.Popup("Max Size", selectedSizeIndex, sizeOptions.Select(size => size.ToString()).ToArray());
			GUILayout.Space(10);

			if (GUILayout.Button("Change Max Size"))
			{
				ChangeMaxSize();
			}
		}

		void ChangeMaxSize()
		{
			if(string.IsNullOrEmpty(folderPath))
			{
				return;
			}

			int maxSize = sizeOptions[selectedSizeIndex];
			string[] textureGuids = AssetDatabase.FindAssets("t:Texture", new string[] { folderPath });

			foreach (string guid in textureGuids)
			{
				string path = AssetDatabase.GUIDToAssetPath(guid);
				TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;

				if (importer != null && importer.maxTextureSize != maxSize)
				{
					importer.maxTextureSize = maxSize;
					AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
				}
			}

			Debug.Log("Textures' max sizes have been changed to " + maxSize);
		}

	}

}

これは選択したフォルダ内のテクスチャの最大サイズを一括で変更するエディタ拡張となっています(GUIは下の画像のような感じ)。

エディタ拡張の例

プロジェクト内のテクスチャサイズをいちいち手作業で変更するのは大変なので、その手間を省く目的で作りました。

サンプルの使い方

Unityエディタのメニューバー→「ツール」→「KurokumaSoft」→「Change Texture Max Size」を選択するとウィンドウが表示されます。そのウィンドウの「Select Folder」ボタンから対象のフォルダを選択し、好きな最大サイズを選んで「Change Max Size」ボタンを押してください。そうすると指定したフォルダ内のテクスチャの最大サイズが指定したサイズになります。

サンプルの処理の解説

このサンプルは次の3つの関数で構成されています。

  • ShowWindow関数
  • OnGUI関数
  • ChangeMaxSize関数

ShowWindow関数でウィンドウを表示し、OnGUI関数で表示の更新を行います。またChangeMaxSize関数はテクスチャの最大サイズの変更処理を行うこのエディタ拡張独自の関数です。

ShowWindow関数

このエディタ拡張用のウィンドウを表示するための関数です。名前は何でもOKですが、とりあえずstaticな関数である必要があります。

この中にはGetWindow関数を書いておきましょう。

OnGUI関数

OnGUI関数内はウィンドウ内のGUIを表示・更新するための特殊な関数です。ウィンドウ内に表示するGUI要素をこの関数内に書いて、必要な処理を実行したり、状況に応じてGUIの内容を変更したりします。

エディタ拡張を作るうえで最初に困るのがこのOnGUI関数内にどのようにGUI要素を書くか?という部分だと思うのでここは丁寧に解説しておきます。

まず、OnGUI関数内の冒頭では「GUILayout.Label」を使って見出しの表示を行っています。ただそのままだと後続のボタンとの間隔が詰まりすぎてしまうので「GUILayout.Space」を使って適当に隙間を挿入しています。

GUILayout.Label("Change Max Size of Textures", EditorStyles.boldLabel);
GUILayout.Space(10);

次のif文では「Select Folder」というボタンを押したらフォルダ選択画面が出るようにしています。

if(GUILayout.Button("Select Folder"))
{
	path = EditorUtility.OpenFolderPanel("Select Folder", "Assets", "");
}

フォルダ選択画面を出すには「EditorUtility.OpenFolderPanel」という関数を使います。詳細は公式リファレンスをご参照ください。

次に、もし先ほどのボタンを押してフォルダを選択していたら、どのフォルダを選択中かを表示します。

if (!string.IsNullOrEmpty(path))
{
	folderPath = path.Replace(Application.dataPath, "Assets");
	GUILayout.Label("Selected Folder:\n" + folderPath);
	GUILayout.Space(20);
}

その次はテクスチャの最大サイズを選択できるドロップダウンメニューを表示します。ドロップダウンメニューを表示するには「EditorGUILayout.Popup」という関数を使用します。

selectedSizeIndex = EditorGUILayout.Popup("Max Size", selectedSizeIndex, sizeOptions.Select(size => size.ToString()).ToArray());
			GUILayout.Space(10);

最後に実際の処理を行うためのボタンを配置します。

if (GUILayout.Button("Change Max Size"))
{
	ChangeMaxSize();
}

これで今回のエディタ拡張に必要なGUIを用意できました。

ChangeMaxSize関数

さてChangeMaxSize関数は今回のエディタ拡張の実際の処理を行う独自の関数です。この部分に関してはエディタ拡張の説明から逸れてしまいますので詳しい説明はしませんが、処理内容としては指定したフォルダ内からテクスチャを探して、その最大サイズを変更するというような内容になっています。

OnGUI関数内でよく使うGUI要素について

では最後になりますがOnGUI関数内で頻繁に使うGUI要素についてザックリまとめておきます。最低限下記のGUI要素を覚えておけば簡単なエディタ拡張のGUIならサクッと作れるようになります。

  1. GUILayout.Label
  2. GUILayout.Button
  3. GUILayout.Space
  4. GUILayout.Toggle

GUILayout.Label

見出しを表示するGUI要素です。太字にすることもできます。

GUILayout.Button

エディタ拡張には必要不可欠なボタンです。押した時にtrue、何もしなければfalseを返します。

GUILayout.Space

指定した分だけGUIに余白を設けます。

GUILayout.Toggle

(今回のサンプルでは登場しませんでしたが)チェックボックスを表示します。1つ目の引数にチェックの有無を格納するためのbool型の変数を指定し、戻り値も同じ変数で受け取るようにすることで上手く機能するようになります。

おわりに

以上、Unityのエディタ拡張の基本的な作り方を解説しました。既に書いた通りエディタ拡張を自作できるようになるとゲーム開発がとても捗るようになって快適になりますので、ぜひ上記の内容を足掛かりにしていただきエディタ拡張を作れるようになって頂ければと思います。

この記事がUnityでのゲーム開発のお役に立てば幸いです。