可编写脚本的对象是否可以具有特定类型的字段,并且可以根据另一个字段的类型来确定该类型?例如:
public class ItemObject : ScriptableObject
{
public ItemType type;
public Item data = new Item();
}
ItemType 是一个枚举
public enum ItemType
{
Physical,
Magical
}
Item 是一个基本类,还有另外 2 个类继承自它,MagicalItem 和 PhysicalItem。
[System.Serializable]
public class MagicalItem : Item {
public string passive;
public MagicalItem() {
passive = "";
}
}
ect.
我希望 ItemObject 能够在编辑器中从这些选项中进行选择,或者当我向游戏中添加新的项目类型时选择更多选项。我一直无法找到解决方案,但我的想法是根据类型在 Awake() 上设置数据类型,但我无法让它发挥作用。 IE 是这样的:
private void Awake() {
if(type == ItemType.Magical) {
data = new MagicalItem();
} else {
data = new PhysicalItem();
}
}
有没有更好的方法来解决这个问题?
Thanks!
解决这个问题很有趣。
我发现的这个技巧实际上是一个新东西,[SerializeReference] https://docs.unity3d.com/ScriptReference/SerializeReference.html,它可以做一些事情,其中之一可以让您进行多态序列化,这是这个问题所需要的。
解决这个问题的主要步骤:
- Add
[SerializeReference]
to the data
field.
- 添加一个静态方法,根据所需的类型创建新实例
- 添加一个自定义编辑器来检查
type
字段进行更改,如果发生更改,则使用上述方法创建一个新实例并将其分配给data
field
总而言之,这会给你这样的结果:
[CreateAssetMenu(fileName = "Data", menuName = "Inventory/Item", order = 1)]
public class ItemObject : ScriptableObject
{
[CustomEditor(typeof(ItemObject))]
public class ItemObjectInspector : Editor
{
SerializedProperty m_type;
SerializedProperty m_data;
private void OnEnable()
{
m_type = serializedObject.FindProperty("type");
m_data = serializedObject.FindProperty("data");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_type);
if (EditorGUI.EndChangeCheck())
{
m_data.managedReferenceValue =
ItemObject.CreateBlankData((ItemType)m_type.intValue);
}
// avoid drawing type a second time
// avoid drawing annoying Script field
DrawPropertiesExcluding(serializedObject, new string[] { "type", "m_Script" });
serializedObject.ApplyModifiedProperties();
}
}
[System.Serializable]
public enum ItemType
{
Physical,
Magical
}
// Determines how to create an Item from each ItemType
public static Item CreateBlankData(ItemType type)
{
switch (type)
{
default:
case ItemType.Physical:
return new PhysicalItem();
case ItemType.Magical:
return new MagicalItem();
}
}
[System.Serializable]
public class Item
{
[SerializeField] public string typeDescription;
}
[System.Serializable]
public class MagicalItem : Item
{
[SerializeField] string elementName;
public MagicalItem() { typeDescription = "Magical"; elementName = "fire"; }
}
[System.Serializable]
public class PhysicalItem : Item
{
[SerializeField] float materialHardness;
public PhysicalItem() { typeDescription = "Physical"; materialHardness = 1f; }
}
public ItemType type;
[SerializeReference] public Item data;
}
注意:为了简洁起见,以上所有类都只是内部类。它们可以是单独的类或内部类,没有任何问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)