在我的游戏中,我有一个神奇的系统,它使用命令模式来存储步骤。如何在检查器中分配不是从MonoBehavior
或ScriptableObject
派生的抽象命令(或者只是不硬编码(?
下面我有一个最小的例子,注意SpellCommand
既不是从MonoBehavior
派生的,也不是从ScriptableObject
派生的。
public abstract class SpellCommand {
public SpellCommand (int power = -1) {
this.power = power;
}
public abstract void Cast();
}
下面是一个咒语可能看起来像
public class SampleSpell : SpellCommand {
public SampleSpell(int power) : base(power: power) { }
public override void Cast() {
Debug.Log("Sample Spell Cast");
}
}
最后一个MonoBehavior
调用它
public class TestSpellInvoker : MonoBehaviour
{
public SpellCommand testSpell;
void Start() {
testSpell.Cast();
}
}
由于我知道Unity不支持非MonoBehavior
派生的抽象类的序列化,所以我编写了自己的检查器脚本来分配和显示testSpell
的内容,但每当我进入播放模式时,它似乎都被清空了。
我已经考虑过删除所有多态性,并简单地使用一个大的Enum
来表示子类,但这会引入大量的复杂性,而且感觉非常违背C#和OOP的精神。我也考虑过使用ScriptableObject
s,但这需要(在我的情况下(将潜在的数千个ScriptableObject
实例保存为文件,然后我将不得不争论这些文件(尽管也就是说,我对ScriptableObject
s的了解非常初级,所以我可能会遗漏一些东西(。
- 您的抽象类和实现程序应该是
Serializable
。若并没有,那个么数据将不会存储在场景中,也不会存储在预制件中 - 我还没有在
MonoBehaviour
中使用过它,但它在ScriptableObject
中有效。使用SerializableReference而不是SerializableField
。只要您遵循文档中的规则(Serializable,而不是来自UnityEngine.Object,不是值类型,也不是字典(,那么您就可以存储实现者实例
注意:如果您这样做,您将需要根据实现者调整您的自定义检查器以显示数据。