简体   繁体   English

Unity:在检查器中分配抽象实例 object

[英]Unity: Assign instance of abstract object in the inspector

In my game, I have a magic system that uses a command-pattern to store the steps.在我的游戏中,我有一个魔法系统,它使用命令模式来存储步骤。 How can I assign an abstract command not derived from MonoBehavior or ScriptableObject in the inspector (or just not hard-coding it)?我如何在检查器中分配一个不是从MonoBehaviorScriptableObject派生的抽象命令(或者只是不对其进行硬编码)?

Below I have the minimum example, note that SpellCommand does not derive from MonoBehavior nor ScriptableObject .下面我有一个最小的例子,请注意SpellCommand不是从MonoBehaviorScriptableObject派生的。

public abstract class SpellCommand {
    public SpellCommand (int power = -1) {
        this.power = power;
    }
    public abstract void Cast();
}

And here is what a spell might look like这是咒语的样子

public class SampleSpell : SpellCommand {
    public SampleSpell(int power) : base(power: power) { }

    public override void Cast() {
        Debug.Log("Sample Spell Cast");
    }
}

And finally a MonoBehavior to invoke it最后一个MonoBehavior来调用它

public class TestSpellInvoker : MonoBehaviour
{
    public SpellCommand testSpell;

    void Start() {
        testSpell.Cast();
    }
}

Since I know Unity doesn't support serialization of abstract classes not derived from MonoBehavior , I wrote my own inspector script to assign and display the contents of testSpell but whenever I enter play mode, it seems to be nulled out.因为我知道 Unity 不支持不是从MonoBehavior派生的抽象类的序列化,所以我编写了自己的检查器脚本来分配和显示testSpell的内容,但是每当我进入播放模式时,它似乎都被取消了。

I've considered removing all polymorphism and simply using a large Enum to represent subclasses, but that would introduce a ton of complexity and it feels very much against the spirit of C# and OOP. I've also considered using ScriptableObject s, but that would require (in my case) having potentially thousands of ScriptableObject instances saved as files that I would then have to wrangle (although that being said my knowledge of ScriptableObject s is pretty elementary so I might be missing something).我已经考虑过删除所有多态性并简单地使用一个大的Enum来表示子类,但这会引入大量的复杂性并且感觉非常违背 C# 和 OOP 的精神。我也考虑过使用ScriptableObject ,但那会需要(在我的情况下)可能有数千个ScriptableObject实例保存为文件,然后我将不得不争论(尽管据说我对ScriptableObject的知识非常初级,所以我可能会遗漏一些东西)。

  1. Your abstract class and implementors should be Serializable .您的抽象 class 和实现者应该是Serializable If it's not, your data won't be stored either in scene, or in a prefab.如果不是,您的数据将不会存储在场景或预制件中。
  2. I haven't used it in a MonoBehaviour but this works in a ScriptableObject .我没有在MonoBehaviour中使用它,但这在ScriptableObject中有效。 Use SerializableReference instead of SerializableField .使用SerializableReference而不是SerializableField As long as you follow the rules in the documentation (Serializable, not from UnityEngine.Object, not a value type, not a dictionary), then you can store the implementors instances.只要您遵循文档中的规则(可序列化,不是来自 UnityEngine.Object,不是值类型,不是字典),您就可以存储实现实例。

NOTE: If you do this, you'll need to adjust your custom inspector to display the data depending on the implementor.注意:如果您这样做,您将需要调整您的自定义检查器以根据实施者显示数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM