【Unity】【エディタ拡張】フィールドの値などをインスペクタで横に並べて表示する 
2022/10/01 Sat [edit]
プロジェクトが大きくなってくるとデバッグが大変になってくるね。VRM Live Viewer は既に4周年を超えてしまったこともあって、とても巨大なシステムになってしまっている。Unity では Debug.Log を使うことも多いのだが、多くのオブジェクトがあると個々の状態が調べづらいので、最近はよくインスペクタをデバッグ代わりに使っている。
ただ独自クラス・構造体などを使うことも多いので、デフォルトだと全て縦に並んでしまうんだよね。なので Vector3 などの (x, y, z) のようにまとまってる要素は横に並べてすっきり表示したいことが多い。
そんな時は エディタ拡張の PropertyDrawer を使うと良い。簡単なものをメモとして載せておくので、色々応用すると良いだろう。

(※) Unity 2020.3.34f1 / Windows11(x64) で確認
●X, Y, Z 各軸の true / false 構造体の定義とインスペクタでの表示(PropertyDrawer)
using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Example //※名前は任意
{
//定義クラス・構造体
/// <summary>
/// X, Y, Z 各軸の true / false 構造体
/// </summary>
[Serializable]
public struct AxisBool
{
public bool x;
public bool y;
public bool z;
public AxisBool(bool x, bool y, bool z)
{
this.x = x;
this.y = y;
this.z = z;
}
}
#if UNITY_EDITOR
//エディタ拡張(インスペクタ表示)
[CustomPropertyDrawer(typeof(AxisBool))]
public class AxisBoolDrawer : PropertyDrawer
{
static readonly GUIContent X_LABEL = new GUIContent("X");
static readonly GUIContent Y_LABEL = new GUIContent("Y");
static readonly GUIContent Z_LABEL = new GUIContent("Z");
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUIUtility.singleLineHeight;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var xProperty = property.FindPropertyRelative("x");
var yProperty = property.FindPropertyRelative("y");
var zProperty = property.FindPropertyRelative("z");
//名前
label = EditorGUI.BeginProperty(position, label, property);
Rect contentPosition = EditorGUI.PrefixLabel(position, label);
//ラベル
contentPosition.width *= 1f / 3f; //3つ並べる場合 (n 個のとき、1 / n)
EditorGUI.indentLevel = 0;
EditorGUIUtility.labelWidth = 15f; //ラベル幅(適当)
//各要素
EditorGUI.PropertyField(contentPosition, xProperty, X_LABEL);
contentPosition.x += contentPosition.width;
EditorGUI.PropertyField(contentPosition, yProperty, Y_LABEL);
contentPosition.x += contentPosition.width;
EditorGUI.PropertyField(contentPosition, zProperty, Z_LABEL);
EditorGUI.EndProperty();
}
}
#endif
}
ポイントは定義クラス・構造体用の PropertyDrawer を継承したクラスを作ることで([CustomPropertyDrawer] 属性も付ける)、これは以前に書いた「インスペクタで入力不可(Disable)な属性を作る」と同じである。要するに表示位置を計算して描くだけなので、定型処理(文)のように考えた方が楽だろう。
テストは適当に GameObject にアタッチしたスクリプトに、フィールドとして追加すれば良い(public または [SerializeField] 属性を付ける)。
ついでにスクショのもう1つの方も書いておくと、以下のようになる。
●X, Y, Z 各軸の Min~Max 構造体の定義とインスペクタでの表示(PropertyDrawer)
using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Example //※名前は任意
{
//定義クラス・構造体
/// <summary>
/// X, Y, Z 各軸の Min~Max 構造体
/// </summary>
[Serializable]
public struct RangeVector3
{
public float xMin;
public float xMax;
public float yMin;
public float yMax;
public float zMin;
public float zMax;
public RangeVector3(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax)
{
this.xMin = xMin;
this.xMax = xMax;
this.yMin = yMin;
this.yMax = yMax;
this.zMin = zMin;
this.zMax = zMax;
}
}
#if UNITY_EDITOR
//エディタ拡張(インスペクタ表示)
[CustomPropertyDrawer(typeof(RangeVector3))]
public class RangeVector3Drawer : PropertyDrawer
{
static readonly GUIContent X_MIN_LABEL = new GUIContent("X Min");
static readonly GUIContent X_MAX_LABEL = new GUIContent("X Max");
static readonly GUIContent Y_MIN_LABEL = new GUIContent("Y Min");
static readonly GUIContent Y_MAX_LABEL = new GUIContent("Y Max");
static readonly GUIContent Z_MIN_LABEL = new GUIContent("Z Min");
static readonly GUIContent Z_MAX_LABEL = new GUIContent("Z Max");
const float lineSpace = 2f; //行間
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUIUtility.singleLineHeight * 3 + lineSpace * 2;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var xMinProperty = property.FindPropertyRelative("xMin");
var xMaxProperty = property.FindPropertyRelative("xMax");
var yMinProperty = property.FindPropertyRelative("yMin");
var yMaxProperty = property.FindPropertyRelative("yMax");
var zMinProperty = property.FindPropertyRelative("zMin");
var zMaxProperty = property.FindPropertyRelative("zMax");
//名前
label = EditorGUI.BeginProperty(position, label, property);
Rect contentPosition = EditorGUI.PrefixLabel(position, label);
//ラベル
contentPosition.width *= 1f / 2f; //2つ並べる場合 (n 個のとき、1 / n)
EditorGUI.indentLevel = 0;
EditorGUIUtility.labelWidth = 40f; //ラベル幅(適当)
//各要素
contentPosition.height = EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(contentPosition, xMinProperty, X_MIN_LABEL);
contentPosition.x += contentPosition.width;
EditorGUI.PropertyField(contentPosition, xMaxProperty, X_MAX_LABEL);
contentPosition.x -= contentPosition.width;;
contentPosition.y += EditorGUIUtility.singleLineHeight + lineSpace;
EditorGUI.PropertyField(contentPosition, yMinProperty, Y_MIN_LABEL);
contentPosition.x += contentPosition.width;
EditorGUI.PropertyField(contentPosition, yMaxProperty, Y_MAX_LABEL);
contentPosition.x -= contentPosition.width;;
contentPosition.y += EditorGUIUtility.singleLineHeight + lineSpace;
EditorGUI.PropertyField(contentPosition, zMinProperty, Z_MIN_LABEL);
contentPosition.x += contentPosition.width;
EditorGUI.PropertyField(contentPosition, zMaxProperty, Z_MAX_LABEL);
EditorGUI.EndProperty();
}
}
#endif
}
こちらも contentPosition を横・縦に移動して描いているだけと考えれば色々応用は利くだろう。日本語だとラベル幅からはみ出るかも知れないが(私は英語インターフェイスに慣れてしまってるので、日本語版は使ったことがない)、その辺はよしなに(笑)。
(参考)
・【Unity】最小と最大の値を管理する構造体を作りたいの
(関連記事)
【Unity】インスペクタで入力不可(Disable)な属性を作る
【Unity】インスペクタの表示項目を動的に変更する
【Unity】インスペクタの UnityEvent を並べ替え可能にする
【Unity】インスペクタの配列やリストを並べ替え可能にする
【Unity】インスペクタの値を保持したまま変数をリネームする
【Unity】独自のギズモ(Gizmo)を表示する
- 関連記事
-
-
【Unity】【C#】SmoothFollow3(SmoothFollow に回転・遠近・高さ操作とピンチ・スワイプとの連携機能を付けた拡張版)
-
【Unity】【C#】符号(方向)付き角度を、2Dの外積を使って求める [2D]
-
【Unity】【C#】ゲームパッドの右スティックを使えるようにする
-
【Unity】【エディタ拡張】フィールドの値などをインスペクタで横に並べて表示する
-
【Unity】【エディタ拡張】独自のギズモ(Gizmo)を表示する
-
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/419-2bb82cf0
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |