【问题标题】:Custom Property Drawers for Generic Classes C# Unity通用类 C# Unity 的自定义属性抽屉
【发布时间】:2014-09-13 14:26:16
【问题描述】:

我在检查器中显示 Serializable 泛型类时遇到问题。

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 不会在检查器中显示任何内容。它应该显示一个文本字段。

我相信这是由于该类的通用性质,但我一直无法找到任何人使用具有通用类的自定义属性抽屉的示例。

我的问题是 - 这可能吗?我从允许文本字段按预期显示的代码中遗漏了什么?如果目前的代码不可能,那么对于泛型类的属性抽屉是否有任何解决方法?

感谢您的宝贵时间!

【问题讨论】:

    标签: c# generics properties unity3d drawer


    【解决方案1】:

    这不起作用,因为 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 { ... }
    

    这并不优雅,但解决了问题。

    【讨论】:

      【解决方案2】:

      我不是绝对肯定的,但根据我过去的经验,Unity 不支持通用类的 CustomPropertyDrawers。

      【讨论】:

      • 感谢您的回复。如果你是对的,我可能需要尝试某种包装器,但我也不确定它是如何工作的。
      • 我也遇到了类似的问题,但在几个小时的效率低下后我就放弃了。祝你好运!
      【解决方案3】:

      一种解决方法是从非泛型抽象基类继承。这是因为 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 ();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 2020-06-29
        • 2020-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-31
        相关资源
        最近更新 更多