1.对于ScriptableObject 的属性 自定义显示,需要使用CustomPropertyDrawer
2.实现规程
需要自定义属性的脚本:
[System.Serializable]
public class TargetElementFinder
{
public FindTargetType Type;
public string Id;
public Coordinate SelfRange;
public List<Coordinate> TileRange;
}
用到的类型脚本:
public enum FindTargetType
{
Self=0,
Target=1,
Player=2,
Range=3,
Global=4,
SelfRange=5,
}
[System.Serializable]
public struct Coordinate
{
public int X;
public int Y;
}
CustomPropertyDrawer 编辑器实现:
using System;
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(TargetElementFinder))]
public class TargetElementFinder_ParamEditor : PropertyDrawer
{
private const int HeightOneLine = 20;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (!property.isExpanded)
{
EditorGUI.PropertyField(position, property, new GUIContent("TargetElementFinder"), true);
return;
}
var headPosition = new Rect(position.x, position.y, position.width, HeightOneLine);
EditorGUI.PropertyField(headPosition, property, new GUIContent("TargetElementFinder"), false);
EditorGUI.indentLevel += 2;
var typeProperty = property.FindPropertyRelative("Type");
var typePosition = new Rect(position.x, position.y + HeightOneLine, position.width, HeightOneLine);
typeProperty.enumValueIndex = EditorGUI.Popup(typePosition, "Type", typeProperty.enumValueIndex, typeProperty.enumDisplayNames);
var keyValueType = (FindTargetType) Enum.GetValues(typeof(FindTargetType)).GetValue(typeProperty.enumValueIndex);
switch (keyValueType)
{
case FindTargetType.Self:
case FindTargetType.Target:
case FindTargetType.Player://这些类型 没有参数
break;
case FindTargetType.Range:
case FindTargetType.Global://这些类型有两个参数
var idProperty = property.FindPropertyRelative("Id");
var idPosition = new Rect(typePosition.x, typePosition.y + HeightOneLine, typePosition.width, HeightOneLine);
idProperty.stringValue = EditorGUI.TextField(idPosition, "Id", idProperty.stringValue);
var tileRangeProperty = property.FindPropertyRelative("TileRange");
var tileRangePosition = new Rect(idPosition.x, idPosition.y + HeightOneLine, idPosition.width, HeightOneLine);
EditorGUI.PropertyField(tileRangePosition, tileRangeProperty, new GUIContent("TileRange"), true);
break;
case FindTargetType.SelfRange://显示类参数
var selfRangeProperty = property.FindPropertyRelative("SelfRange");
var selfRangePosition = new Rect(typePosition.x, typePosition.y + HeightOneLine, typePosition.width, HeightOneLine);
EditorGUI.PropertyField(selfRangePosition, selfRangeProperty);
break;
default:
throw new ArgumentOutOfRangeException();
}
EditorGUI.indentLevel -= 2;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (!property.isExpanded) return HeightOneLine;
var typeProperty = property.FindPropertyRelative("Type");
var keyValueType = (FindTargetType)Enum.GetValues(typeof(FindTargetType)).GetValue(typeProperty.enumValueIndex);
switch (keyValueType)
{
case FindTargetType.Self:
case FindTargetType.Target:
case FindTargetType.Player://属性展开了,由于没有参数,只有一个属性和变量名 高度=一行高度*2
return HeightOneLine*2;
case FindTargetType.Range:
case FindTargetType.Global:
var tileRangeProperty = property.FindPropertyRelative("TileRange");
if (tileRangeProperty.isExpanded)
{
var arayCount = tileRangeProperty.arraySize;
return HeightOneLine * (5 + arayCount);
}
else
return HeightOneLine * 4;
case FindTargetType.SelfRange://一共3行属性的显示 高度就*3
return HeightOneLine * 3;
default:
throw new ArgumentOutOfRangeException();
}
}
}
|