通用类的自定义属性抽屉
本文关键字:自定义属性 | 更新日期: 2023-09-27 18:14:26
我在检查器中显示可序列化的泛型类时遇到了麻烦。
Serializable泛型类如下:
using UnityEngine;
using System;
using System.Collections;
[Serializable]
public class GenericClass<T> where T : struct
{
[SerializeField]
string _serializedString;
public string SerializedString
{
get { return _serializedString; }
set { _serializedString = value; }
}
... // Functions using the generic type
}
自定义属性抽屉如下:
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(GenericClass<>))]
public class GenericClassDrawer: PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty stringProperty = property.FindPropertyRelative("SerializedString");
stringProperty.stringValue = EditorGUI.TextField(position, stringProperty.stringValue);
}
}
和MonoBehaviour我使用的测试泛型类如下:
using UnityEngine;
using System.Collections;
public class TestClass : MonoBehaviour
{
enum BasicEnum
{
First,
Second,
Third,
Fourth
}
[SerializeField]
GenericClass<BasicEnum> _editorEnum;
}
使用当前代码,MonoBehaviour TestClass不会在检查器中显示任何内容。它应该显示一个文本字段。
我相信这是由于类的泛型性质,但我一直无法找到任何人使用自定义属性抽屉与泛型类的例子。
我的问题是——这可能吗?我从允许文本字段按预期显示的代码中缺少什么?如果它是不可能的,因为代码目前是有任何解决方案的属性抽屉为泛型类?
感谢您的宝贵时间!这不起作用,因为Unity目前(4.x/5.0)不序列化泛型类。序列化泛型的一个技巧是继承它们。比如在这个例子中,你可以输入:
[Serializable]
class GenericClassInt: GenericClass<int> { ... }
[Serializable]
class GenericClassFloat: GenericClass<float> { ... }
然后你可以有编辑器的字段:
[CustomPropertyDrawer(typeof(GenericClassInt))]
[CustomPropertyDrawer(typeof(GenericClassFloat))]
public class GenericClassDrawer: PropertyDrawer { ... }
这不是很优雅,但解决了问题。
一种解决方法是从非泛型抽象基类继承。这是因为property.FindPropertyRelative(…)在运行时而不是编译时查找值,所以它在具体的运行时实例中查找值。
[Serializable]
public abstract class Generic { }
[Serializable]
public abstract class Generic<T> : Generic {
public T value;
}
[Serializable]
public class GenericInt : Generic<int> { }
[Serializable]
public class GenericFloat : Generic<float> { }
[CustomPropertyDrawer (typeof (Generic), true)]
public class IngredientDrawer : PropertyDrawer {
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty (position, label, property);
position = EditorGUI.PrefixLabel (position, GUIUtility.GetControlID (FocusType.Passive), label);
EditorGUI.PropertyField (position, property.FindPropertyRelative ("value"), GUIContent.none);
EditorGUI.EndProperty ();
}
}
基于您的代码:您正在通过名称SerializedString请求,它对应于一个属性和一个非序列化字段。输入以下代码接收SerializedProperty:
SerializedProperty stringProperty = property.FindPropertyRelative("_serializedString");
你应该请求一个FIELD,而不是一个属性
我不是绝对肯定的,但根据我过去的经验,Unity不支持通用类的custompropertydrawer