通用类的自定义属性抽屉

本文关键字:自定义属性 | 更新日期: 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