我有一个类Container<TKey, TValue>,它是一个带有键TKey和值的对象,可以是TValue相同容器的列表:
using System.Collections.Generic;
using System;
using UnityEngine;
namespace Adapter.Containers
{
[Serializable]
public class Container<TKey, TValue>
{
public Container() : this(default) { }
public Container(TKey key) : this(key, default) { }
public Container(TKey key, TValue value)
{
m_Key = key;
m_Value = value;
}
[SerializeField] private TKey m_Key;
[SerializeField] private object m_Value;
public object this[TKey name]
{
get
{
if (GetContainer(name) is Container<TKey, TValue> container)
return container;
else if (GetStore(name) is TValue elementary)
return elementary;
throw new ArgumentException("Cannot get value because store unknown type");
}
set
{
if (value is Container<TKey, TValue> container)
SetContainer(name, container);
else if (value is TValue elementary)
SetStore(name, elementary);
throw new ArgumentException("Cannot set value because this type not support");
}
}
public TKey name { get => m_Key; set => m_Key = value; }
public List<Container<TKey, TValue>> container
{
get
{
if (m_Value is List<Container<TKey, TValue>>)
return m_Value as List<Container<TKey, TValue>>;
return null;
}
set
{
if (value is not null)
m_Value = value;
throw new ArgumentException("Cannot set not container value by container property");
}
}
public TValue store
{
get
{
if (m_Value is TValue)
return (TValue)m_Value;
return default;
}
set
{
if (value is not null)
m_Value = value;
throw new ArgumentException("Cannot set unacceptable type value by store property");
}
}
public ContainerType type => m_Value is List<Container<TKey, TValue>> ? ContainerType.Container : m_Value is TValue ? ContainerType.Store : ContainerType.Unknown;
public Container<TKey, TValue> GetContainer(TKey name) => container[container.FindIndex(item => item.name.Equals(name))]; // Получение по индексу просто для эстетичности
public void SetContainer(TKey name, Container<TKey, TValue> value) => container[container.FindIndex(item => item.name.Equals(name))] = value;
public TValue GetStore(TKey name) => container.Find(item => item.name.Equals(name)).store;
public void SetStore(TKey name, TValue value) => container.Find(item => item.name.Equals(name)).store = value;
}
}
我还有一个ContainerPropertyDrawer用于渲染此类的类:
using UnityEditor;
using UnityEngine;
namespace Adapter.Containers.Editor
{
[CustomPropertyDrawer(typeof(Container<,>))]
public class ContainerPropertyDrawer : PropertyDrawer
{
private ContainerType m_ContainerType = ContainerType.Unknown;
public ContainerType containerType { get => m_ContainerType; set => m_ContainerType = value; }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
SerializedProperty keyProperty = property.FindPropertyRelative("m_Key");
SerializedProperty valueProperty = property.FindPropertyRelative("m_Value");
EditorGUI.LabelField(position, label);
EditorGUILayout.PropertyField(keyProperty);
m_ContainerType = (ContainerType)EditorGUILayout.EnumPopup(m_ContainerType);
if (m_ContainerType != ContainerType.Unknown)
if (m_ContainerType == ContainerType.Container)
EditorGUILayout.PropertyField(valueProperty, true);
else
EditorGUILayout.ObjectField(valueProperty.objectReferenceValue, typeof(object), true);
}
}
}
我遇到的问题是,首先,它会更改同一列表中的所有元素(不是特别重要),其次,不会为我显示值字段(当我尝试绘制该字段时m_ContainerType会出现错误,据我所知,unity 不想正常接收具有或不具有类型的字段?)SerializedProperty is nullm_Valueobject