トップ > 【Unity】エディター拡張方法をまとめます! > 【Unity】両端編集可能なスライダーを表示するエディター拡張を紹介します!
更新日 2022/7/11

【Unity】両端編集可能なスライダーを表示するエディター拡張を紹介します!

両端編集可能なスライダーを表示するEditorGUI.MinMaxSlider関数があるのでエディター拡張してインスペクターに簡単に表示できるようにします。

MinMaxRange

属性にRangeAttributeを使ってみる

最小値と最大値が属性に欲しいので両方持っているRangeAttributeを使ってみます。
スライダー表示のようにRange属性をVector2に付けてみます。

[Range(0f, 1f)]
public Vector2 test;
MinMaxSlider_RangeAttribute

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);
MinMaxRange_WithoutEdit

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の改良

インスペクター上のスライダー表示を元に改良してみましょう。

RangeLayout

スライダーのインスペクター上の幅の構成は上の図のようになっています。
スライダー本体の幅(青い部分)は全体の幅(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();
}
}
}

インスペクター上で次のように表示されます。

MinMaxRange

今回は両端を編集可能なスライダーを作成してみました。
どんどんエディター拡張して快適にUnityエディターを使えるようにしましょう。


関連ページ


Copyright ©2022 - 2024 うにぉらぼ