【Unity】両端編集可能なスライダーを表示するエディター拡張を紹介します!
両端編集可能なスライダーを表示するEditorGUI.MinMaxSlider関数があるのでエディター拡張してインスペクターに簡単に表示できるようにします。
属性にRangeAttributeを使ってみる
最小値と最大値が属性に欲しいので両方持っているRangeAttributeを使ってみます。
スライダー表示のようにRange属性をVector2に付けてみます。
[Range(0f, 1f)]
public Vector2 test;
floatかint以外はお断りされるので属性から自作しましょう。
MinMaxRange属性を作る
RangeAttributeをほぼそのまま使ってMinMaxRangeAttributeクラスを実装します。
RangeAttributeのソースコードは公開されていますので
Unityのリファレンスコードをゲットしようを参照して入手して下さい。
MinMaxRangeAttribute.cs
using System;
namespace UnityEngine
{
[AttributeUsage(AttributeTargets.Field)]
public class MinMaxRangeAttribute : PropertyAttribute
{
public readonly float min;
public readonly float max;
public MinMaxRangeAttribute(float min, float max)
{
this.min = min;
this.max = max;
}
}
}
MinMaxRangeDrawerの実装
MinMaxRangeAttribute用のMinMaxRangeDrawerの実装します。
EditorGUI.MinMaxSliderで両端を編集できるスライダーが表示できます。
その他の実装詳細についてはVector4を1行で表示するエディター拡張を参照して下さい。
[MinMaxRange(0f, 1f)]
public Vector2 minMaxRange = new Vector2(0.25f, 0.75f);
MinMaxRangeDrawer.cs
using UnityEngine;
namespace UnityEditor
{
[CustomPropertyDrawer(typeof(MinMaxRangeAttribute))]
public class MinMaxRangeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
label = EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginChangeCheck();
var range = attribute as MinMaxRangeAttribute;
float minValue = property.vector2Value.x;
float maxValue = property.vector2Value.y;
EditorGUI.MinMaxSlider(position, label, ref minValue, ref maxValue, range.min, range.max);
if(EditorGUI.EndChangeCheck())
{
property.vector2Value = new Vector2(minValue, maxValue);
}
EditorGUI.EndProperty();
}
}
}
これでも良いのですが編集中の数値が分からず不便ですね。
MinMaxRangeDrawerの改良
インスペクター上のスライダー表示を元に改良してみましょう。
スライダーのインスペクター上の幅の構成は上の図のようになっています。
スライダー本体の幅(青い部分)は全体の幅(position.width)から上記の全てを引けば計算できます。
EditorGUI.kPrefixPaddingRightとEditorGUI.kSpacingはinternalスコープで直接呼び出せませんので変数を定義します。
const float kPrefixPaddingRight = 2;
const float kSpacing = 5;
ソースコードは少し複雑になりますが以下の通りです。
改良版MinMaxRangeDrawer.cs
using UnityEngine;
namespace UnityEditor
{
[CustomPropertyDrawer(typeof(MinMaxRangeAttribute))]
public class MinMaxRangeDrawer : PropertyDrawer
{
const float kPrefixPaddingRight = 2;
const float kSpacing = 5;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
label = EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginChangeCheck();
var range = attribute as MinMaxRangeAttribute;
float minValue = property.vector2Value.x;
float maxValue = property.vector2Value.y;
Rect labelPosition = new Rect(position.x, position.y, EditorGUIUtility.labelWidth, position.height);
EditorGUI.LabelField(labelPosition, label);
Rect sliderPosition = new Rect(
position.x + EditorGUIUtility.labelWidth + kPrefixPaddingRight + EditorGUIUtility.fieldWidth + kSpacing,
position.y,
position.width - EditorGUIUtility.labelWidth - 2 * (EditorGUIUtility.fieldWidth + kSpacing) - kPrefixPaddingRight,
position.height
);
EditorGUI.MinMaxSlider(sliderPosition, ref minValue, ref maxValue, range.min, range.max);
Rect minPosition = new Rect(position.x + EditorGUIUtility.labelWidth + kPrefixPaddingRight, position.y, EditorGUIUtility.fieldWidth, position.height);
minValue = EditorGUI.FloatField(minPosition, minValue);
Rect maxPosition = new Rect(position.xMax - EditorGUIUtility.fieldWidth, position.y, EditorGUIUtility.fieldWidth, position.height);
maxValue = EditorGUI.FloatField(maxPosition, maxValue);
if (EditorGUI.EndChangeCheck())
{
property.vector2Value = new Vector2(minValue, maxValue);
}
EditorGUI.EndProperty();
}
}
}
インスペクター上で次のように表示されます。
今回は両端を編集可能なスライダーを作成してみました。
どんどんエディター拡張して快適にUnityエディターを使えるようにしましょう。
関連ページ
こちらのページも合わせてご覧下さい。