テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

知っておくと少し幸せになる最低限のエディタ拡張

OnValidate


Unityのエディタ拡張で、実際に使い勝手の良い使って便利で最低限なエディタ拡張手法を紹介しようと思う。他にも「Unity エディタ拡張」で検索すれば色々と出るが、少なくとも自分はこれだけで何とかなってる。

OnValidate

OnValidateを使用すると、エディタからインスペクターの値を変更した際に呼ばれる。
例えばOnValidateに値のmax-minを設定する処理を記述しておけば、変な値が入らなくなるし、
インスペクターの値を変更した際に何か処理を実行したい場合も使える。
ただし、この項目でオブジェクトを生成することは出来ない。

MonoBehaviourを継承したクラスに下のスクリプトを記述する。

    public int speed = 5;
void OnValidate()
{
speed = Mathf.Clamp(speed, 0, 10);
}

参考:



Gizmos

オブジェクトが選択中もしくはシーンに配置されている間、シーンビューに線とか四角を表示する。
Colliderではない当たり判定の可視化やグリッドの補湯現、エリアの判定に使える。ただ長方形を表現したい場合は頑張って記述する必要がある。

MonoBehaviourを継承したクラスに下のスクリプトを記述する。

    // オブジェクト選択中の描画
void OnDrawGizmosSelected()
{
Gizmos.DrawRay(transform.position, transform.right);
}
// 常時描画
void OnDrawGizmos()
{
Gizmos.DrawRay(transform.position, -transform.right);
}

もう少し細かい情報をシーンビューに出したい場合はHandleを使う

参考:



[ContextMenu("コマンド名")]

メソッドにこの属性を追加すると、コンポーネントのメニューからコマンドを呼び出せるようになる。
大量のオブジェクトの配置や整頓等の機能はこちらに記述すると良い。オブジェクト生成ならばこっちでやるべき。

MonoBehaviourからだけでなく、プレハブやScriptableObjectからも呼べる。

    [ContextMenu("CloneMe")]
void CloneMe()
{
for(int i=1; i<5; i++)
{
var obj = (GameObject)GameObject.Instantiate(gameObject);
obj.transform.parent = transform.parent;
obj.transform.localPosition = transform.position + Vector3.right * i;
}
}

参考:



[UnityEditor.MenuItem("コマンド名")]

staticメソッドにこの属性を追加すると、メニューから呼び出せるようになる。
UnityEditorを使うのでスクリプトはEditorフォルダ以下に配置。

使えるのはstaticメソッドな点に注意。

    [UnityEditor.MenuItem("Assets/export hoge")]
public static void Hoge()
{
string text = "hoge", path = "Assets/export.txt";
System.IO.File.WriteAllText(path, text);
UnityEditor.AssetDatabase.ImportAsset(path);
}

コマンド名は「親メニュー/子メニュー」のような形で記述。少なくとも2階層以上必要。
メニューのパスはユーザーが自由に記述出来るが、component等いくつかメニューに使用できないワードもある。

  • File:プロジェクトに関する処理を記述
  • Edit:エディタのアクション系に使用
  • Assets:アセットに関する記述。プロジェクトビューの右クリックから呼び出せる。
  • GameObject:GameObjectの操作に関する記述
  • Window:ウィンドウの開閉処理は大体ここ


参考:



[PreferenceItem(メニュー名)]

Preference内にメニューを追加する。

この中ではGUILayoutやEditorGUILayoutでGUIを記述出来る。単純にメニューを作るだけならWindow作るより楽に作れる。ただし常時表示には向いてない。GUIの表現は[Unity]Unity EditorのInspectorを拡張するが参考になる。

    static string text = string.Empty;
[UnityEditor.PreferenceItem("Hoge")]
static void ExampleOnGUI ()
{
text = UnityEditor.EditorGUILayout.TextField(text);
if( GUILayout.Button("show message"))
{
Debug.Log(text);
}
}

参考:



EditorUserSettings

EditorUserSettingsでプロジェクト単位でエディタ情報を保存する。

// 保存
UnityEditor.EditorUserSettings.SetConfigValue("key", "value");

// 読込
string value = UnityEditor.EditorUserSettings.GetConfigValue("key");

ゲーム内でも使いたい場合は、ScriptableObjectをResourcesに配置しておく方法を検討する


UnityEditorネームスペース下のクラスを使う場合

UnityEditorネームスペースはゲームに含むことが出来ないため、この処理を記述するスクリプトはEditorフォルダに配置しておく。もしくは下のようなプリプロセッサ ディレクティブで囲み、エディタ以外で動作しないようにしておく。

#if UNITY_EDITOR
using UnityEditor;
#endif

#if UNITY_EDITOR
// 処理
#endif

参考:



Unityエディタの改造は凄く楽しいので夢中になってしまうが、Unityエディタを拡張してもゲームは完成しないので注意。手段と目的を違えてはいけない。