'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)?
Below I have the minimum example, note that SpellCommand does not derive from MonoBehavior nor ScriptableObject.
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
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.
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 ScriptableObjects, 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 ScriptableObjects is pretty elementary so I might be missing something).
Solution 1:[1]
- Your abstract class and implementors should be
Serializable. If it's not, your data won't be stored either in scene, or in a prefab. - I haven't used it in a
MonoBehaviourbut this works in aScriptableObject. Use SerializableReference instead ofSerializableField. 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.
NOTE: If you do this, you'll need to adjust your custom inspector to display the data depending on the implementor.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Tricko |
