【发布时间】:2021-02-03 14:44:18
【问题描述】:
我正在尝试创建一个用于在 Unity 中创建游戏项目的工具。我首先创建了一个基类,游戏中的所有游戏元素都从该基类继承:
[System.Serializable]
public class ItemModel
{
public int ID;
public string Name;
public string Description;
public UnityEngine.Sprite Picture;
public int Cost;
public float Weight;
}
然后,基于基类,为特定类型的物品(例如武器类)创建了几个类:
using UnityEngine;
using System;
[Serializable]
public class WeaponModel : ItemModel
{
[Range(0, 10000)] int Damage;
}
要保存关于这个项目的数据,你需要使用一个ScriptableObject,这里我创建了一个Object类型的变量来存储关于游戏项目的所有特定类:
using System;
using UnityEngine;
[System.Serializable]
public enum ItemType
{
Default,
Weapon,
Armory,
Potion,
Food,
Readable
}
[Serializable]
public class ItemData : ScriptableObject
{
public ItemType Type;
public System.Object Item;
public GameObject Prefab;
}
但是这个解决方案对于 EditorGUILayout.PropertyField() 是不正确的,因为它会准确地绘制 Object 类型并且不允许我添加我需要的类。然后我尝试根据枚举 ItemType 使用以下方法将所需的类设置为 Object:
protected void DrawNoSerializedField<T, T2>(System.Object obj)
{
Type objType = typeof(T);
FieldInfo[] varsArray = objType.GetFields();
for (int i = 0; i < varsArray.Length; i++)
{
if(varsArray[i].FieldType == typeof( System.Object))
{
Type Ttype = typeof(T2);
System.Object instance = Activator.CreateInstance(Ttype);
varsArray[i].SetValue(instance, null);
}
}
}
然后这样称呼它:
ItemData data = _window.serializedObject.targetObject as ItemData;
DrawNoSerializedField<ItemData, WeaponModel>(data);
但此刻 varsArray[i].SetValue(instance, null) Unity 抛出错误 MissingMethodException: Default constructor not found for type WeaponModel.
我可以拒绝继承对象类的想法,但在这种情况下,您失去了所创建游戏项目的特异性。
在这种情况下,我如何组织基础项目类,以便我可以创建特定项目(如武器或盔甲)并将它们保存为 ScriptableObject 并在单独的窗口中作为 Unity 中的 EditorGUILayout 实现它们?
【问题讨论】:
-
我可能会让
ItemModel : ScriptableObject和你的ItemData有public ItemModel Item; -
我现在正在学习统一,我认为 derHugo 的意思是,换句话说,当你放弃继承时,统一会更好地工作,相反,use composition. 我真的很挣扎我本人非常习惯基于继承的 OOP
-
@derHugo 根据您的建议,我使用
ItemModel来保存基本信息。对于补充和具体信息,我编写了一个列表,其中包含一个保留string Name和float Value的类。但是这个解决方案看起来很原始...... -
我同意..问题是存储的数据以后应该如何使用?并且:
ScriptableObject的优点是它还可以实现行为 => 你可以例如添加一个public abstract void Use();,每个继承的类型都可以定义自己的行为.. -
@derHugo 在场景中附加到 GameObject 的某种脚本会将此 ScriptableObject 保留为关于其自身的信息。这将有助于与对象和库存系统进行交互。关于 ScriptableObject 中的实现行为...我正在尝试分离逻辑和信息,因此 ScriptableObject 应该保留仅表示有关它们被实现的对象的信息的方法..
标签: c# unity3d game-development