It is late and i cannot wrap my head around this: Is there a quick built in way of supporting Class-Inheritance within the Editor?
I have a baseclass array that i want to fill via the editor
public DropAndPickupEffect[] inventoryTransitionEffects;
I want to insert different subclass-instances into this array, how do i get the Editor to show me some kind of subclass selection for each entry, do i have to write a costum editor, how would this work?
this is my class + 2 example subclasses
[System.Serializable]
public class DropAndPickupEffect {
public virtual void PickUpEffect( ActorController ac ) { Debug.Log("Error, virtual method called"); }
public virtual void DropEffect( ActorController ac ) { Debug.Log("Error, virtual method called"); }
}
[System.Serializable]
public class AttackReplacement: DropAndPickupEffect{
public string attackID;
public AttackSlot slot;
public override void PickUpEffect( ActorController ac ){
Debug.Log("Invoked AttackReplacement");
ac.ReplaceAttack( slot, GetAtt.ByID(attackID) );
}
public override void DropEffect( ActorController ac ){
Debug.Log("Invoked Reversion of AttackReplacement");
ac.RevertAttack( slot );
}
}
[System.Serializable]
public class InvokeAttackOnDrop: DropAndPickupEffect{
public string attackID;
public override void PickUpEffect( ActorController ac ){
Debug.Log("Invoked InvokeOnDrop (does Nothing)");
}
public override void DropEffect( ActorController ac ){
Debug.Log("Invoked Reversion InvokeOnDrop");
GetAtt.ByID(attackID).Invoke( ac.GetMortalObject(), Vector3.zero, new DynPos(Vector3.zero) );
}
}
The problem here is that Unity has no way to edit arbitrary child classes. In order to add an element to this array from the editor, it would have to get a list of all classes that inherit from the base class, let you choose one, and present different fields depending on the type of the child class. Unity just doesn’t have the UI to do that.
Unity doesn’t do well with inheritance in general. It’s kind of a shame, I could be doing some things much cleaner but Unity often times doesn’t like to serialize, or show it in the editor, or some other thing. For example, I’d love to use interfaces to store a list of component references in the editor, but if I recall Unity just doesn’t know what to do with that. So you’ll just have to find a way to work around this.
No, you don’t. Serialization is not polymorphic. I guess a way of doing this, is to use different arrays for different subclasses ONLY in the editor.
Yeah, that is what i am doing now, i have one array for each type of subclass, and just iterate through all of them. I could merge them into a single Array of the baseclass (since i only call the overwrite functions PickUpEffect and DropEffect). But i have to check if there is something like an “OnChange()” for Scriptable Objects so i can automatically do the merge if the Data changes. But in my case a Run-Time merge is no big deal either.
umm… just make the DropAndPickupEffect a ScriptableObject… then make each subclass instance an asset. and it’ll work just fine… you don’t need any special serializer. and it supports Polymorphism just fine.
The idea is very similar to my Command Dispatcher system. Where a GameObject has a monobehaviour “CommandDispatcher” which has a SerializableDictionary <string,CommandDelegatorData>. CommandDelegatorData is an abstract scriptableObject with a single abstract function “Execute(SceneObjectCache data)”. SceneObjectCache is an abstract data container class that holds gameobject state for various project assets that use it. Similar to how the Animator Component holds state for Animator Controllers.
If you want to draw the instance inside the same inspector as the Monobehaviour, then that will take some Editor scripting to pull off. Similar to what my SerializableDictionary does, (which btw I need to update that post…). And in that post I’m using polymorphism. Its a SerializableDictionary<string,NamedInputData> where NamedInputData is an abstract ScriptableObject class but the dictionary is populated with subclass instances like AnyInputData, NamedAxisInputData, and NamedActionInputData.
Haha! Thanks, Why didn’t i see this? This is particulary funny for me because the inventoryTransitionEffects-Array already was on a ScriptableObject, i just had to go one deeper
here is how it looks now, BaseClass Array that stores Subclasses, baseclass inherits from Scriptable Object
public class DropAndPickupEffect : ScriptableObject {
public virtual void PickUpEffect( ActorController ac ) { Debug.Log("Error, virtual method called"); }
public virtual void DropEffect( ActorController ac ) { Debug.Log("Error, virtual method called"); }
public bool destroyOnDrop = false;
public AttackSlot slot = AttackSlot.None;
}
[CreateAssetMenu(fileName = "AttackReplacement", menuName = "ProjectSpecific/DropAndPickupEffect/AttackReplacement", order = 1)]
public class AttackReplacement: DropAndPickupEffect{
public string attackID;
public override void PickUpEffect( ActorController ac ){
Debug.Log("Invoked AttackReplacement");
ac.ReplaceAttack( slot, GetAtt.ByID(attackID) );
}
public override void DropEffect( ActorController ac ){
Debug.Log("Invoked Reversion of AttackReplacement");
ac.RevertAttack( slot );
}
}
[CreateAssetMenu(fileName = "InvokeAttackOnDrop", menuName = "ProjectSpecific/DropAndPickupEffect/InvokeAttackOnDrop", order = 1)]
public class InvokeAttackOnDrop: DropAndPickupEffect{
public string attackID;
public override void PickUpEffect( ActorController ac ){
Debug.Log("Invoked InvokeOnDrop (does Nothing)");
}
public override void DropEffect( ActorController ac ){
Debug.Log("Invoked Reversion InvokeOnDrop");
GetAtt.ByID(attackID).Invoke( ac.GetMortalObject(), Vector3.zero, new DynPos( ac.transform ) );
}
public InvokeAttackOnDrop(){
destroyOnDrop = true;
}
}