ノート: UI Toolkit を使用して Unity エディターを拡張することを強くお勧めします。UI Toolkit は IMGUI よりも新しく柔軟でスケーラブルなソリューションを実現します。
アプリケーションの開発をスピードアップするために、頻繁に使用するコンポーネントのカスタムエディターを作成しましょう。このページでは、ゲームオブジェクトが常に一点を見るようにする簡単なスクリプトの作成方法を紹介します。
using UnityEngine;
public class LookAtPoint : MonoBehaviour
{
public Vector3 lookAtPoint = Vector3.zero;
void Update()
{
transform.LookAt(lookAtPoint);
}
}
再生モードに切り替えると、スクリプトをアタッチしたゲームオブジェクトが、“Look At Point” プロパティに設定した座標に正面を向けます。エディタースクリプトを記述する際に、アプリケーションが実行されていない編集モードの間に、特定のスクリプトを実行することが有効な場合が多くあります。そのためには、以下のように ExecuteInEditMode 属性をクラスに追加します。
using UnityEngine;
[ExecuteInEditMode]
public class LookAtPoint : MonoBehaviour
{
public Vector3 lookAtPoint = Vector3.zero;
void Update()
{
transform.LookAt(lookAtPoint);
}
}
これで、エディターでゲームオブジェクトを動かしたり、Inspector で “Look At Point” の値を変更したりすると、ゲームオブジェクトの回転が更新され、ワールド空間のターゲットポイントを見るようになります。
上記では、編集時に簡単なスクリプトを実行する方法を紹介しましたが、これだけでは独自のエディターツールを作成することはできません。次のステップでは、先ほど作成したスクリプト用に__カスタムエディター__を作成します。
Unity でスクリプトを作成する場合、デフォルトでは MonoBehaviour から継承されます。そのため、スクリプトはゲームオブジェクトにアタッチできるコンポーネントです。ゲームオブジェクトにコンポーネントを配置すると、Inspector にすべてのパブリック変数 (例: 整数、Float、または文字列) を表示および編集するために使用できるデフォルトのインターフェースが表示されます。
LookAtPoint コンポーネントの Inspector は、デフォルトでは以下のようになっています。
カスタムエディターは別のスクリプトであり、このデフォルトレイアウトを選択された任意のエディター制御に置き換えます。
LookAtPoint スクリプト用のカスタムエディターを作成します。
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(LookAtPoint))]
[CanEditMultipleObjects]
public class LookAtPointEditor : Editor
{
SerializedProperty lookAtPoint;
void OnEnable()
{
lookAtPoint = serializedObject.FindProperty("lookAtPoint");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(lookAtPoint);
serializedObject.ApplyModifiedProperties();
}
}
このクラスは Editor から継承する必要があります。CustomEditor 属性は、クラスがどのコンポーネントのエディターとして機能するべきかを Unity に伝えます。CanEditMultipleObjects 属性は、ユーザーがこのエディターで複数のオブジェクトを選択し、すべて同時に変更できることを Unity に伝えます。
Unity が OnInspectorGUI のコードを実行すると、Inspector にエディターが表示されます。ここには任意の GUI コードを配置でき、OnGUI と同じように動作しますが、Inspector 内で実行されます。エディターは、検証するゲームオブジェクトにアクセスするために使用できるターゲットプロパティを定義します。
これは、LookAtPoint コンポーネントの Inspector が新しいエディターでどのように表示されるかを示しています。
これは非常によく似ていますが、“Script” フィールドは現在存在しません。なぜなら、エディタースクリプトにそれを表示するための Inspector コードが加えられていないためです。
ただし、エディタースクリプト内での Inspector の表示を制御できるようになったため、任意のコードを使用して、Inspector フィールドをレイアウトする、ユーザーが値を変更できるようにする、またはグラフィックスやその他のビジュアル要素を表示することも可能になりました。実際のところ、Unity エディター内に表示されるすべての Inspector は、Terrain (地形) システムやアニメーションインポート設定などの複雑なものも含め、独自のカスタムエディターを作成する場合にアクセスできる同じ API で作成されています。
以下に簡単な例を挙げます。これは、ターゲットポイントがゲームオブジェクトの上にあるか下にあるかを示すメッセージが表示されるように、エディタースクリプトを拡張するものです。
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(LookAtPoint))]
[CanEditMultipleObjects]
public class LookAtPointEditor : Editor
{
SerializedProperty lookAtPoint;
void OnEnable()
{
lookAtPoint = serializedObject.FindProperty("lookAtPoint");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(lookAtPoint);
serializedObject.ApplyModifiedProperties();
if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y)
{
EditorGUILayout.LabelField("(Above this object)");
}
if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y)
{
EditorGUILayout.LabelField("(Below this object)");
}
}
}
LookAtPoint コンポーネントの Inspector に、ターゲットポイントがゲームオブジェクトの上か下かを示すメッセージが表示されている様子です。
エディターウィンドウ内でカメラを使ってシーンをレンダリングするなど、あらゆるタイプのインターフェースを描くために、すべての IMGUI コマンドにアクセスできます。
OnSceneGUI は OnInspectorGUI と完全に同じ動作を示しますが、シーンビューで実行される点が異なります。独自の編集コントロールを作成するために、Handles クラスで定義された関数を使用できます。この中にあるすべての関数は 3D シーンビューでの作業用に作成されたものです。
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(LookAtPoint))]
[CanEditMultipleObjects]
public class LookAtPointEditor : Editor
{
SerializedProperty lookAtPoint;
void OnEnable()
{
lookAtPoint = serializedObject.FindProperty("lookAtPoint");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(lookAtPoint);
if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y)
{
EditorGUILayout.LabelField("(Above this object)");
}
if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y)
{
EditorGUILayout.LabelField("(Below this object)");
}
serializedObject.ApplyModifiedProperties();
}
public void OnSceneGUI()
{
var t = (target as LookAtPoint);
EditorGUI.BeginChangeCheck();
Vector3 pos = Handles.PositionHandle(t.lookAtPoint, Quaternion.identity);
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "Move point");
t.lookAtPoint = pos;
t.Update();
}
}
}
2D GUI オブジェクト (例: GUI、EditorGUI) を追加する必要がある場合は、Handles.BeginGUI() と Handles.EndGUI() の呼び出しでそれらをラップする必要があります。