[Inheritance] How to call child method when parent is ScriptableObject?

Hello,
The problem is when i call ActivateAbility() it always calls Ability method but how can i make it call my OffensiveAbility ActivateAbility()? Even if i make an asset by Create > Asset2 and it creates object from OffensiveAbility it still calls only Ability ActivateAbility(). I know it’s because my slot variable is an Ability so it calls Ability method but how can i call from parent class that childs method? It’s going to be more types than offensive etc. Should i just recreate my Ability script and add Enum with abiltiy type? Or is it easy way to call child method?

//Edit
Even tried:

hotBarSlot.gameObject.GetComponent<OffensiveAbility>().

but got an error ArgumentException: GetComponent requires that the requested component 'OffensiveAbility' derives from MonoBehaviour or Component or is an interface.

public class Ability : ScriptableObject
{
     [SerializeField] private string id;
    public string ID { get { return id; } }

    public string abilityName;
    public int lvlRequired;
    public int abilityLvl;
    public Sprite Icon;

    public GameObject abilityPrefab;
    public float abilitySpeed;
  
    protected static readonly StringBuilder sb = new StringBuilder();
  
    private void OnValidate()
    {
#if UNITY_EDITOR
        string path = AssetDatabase.GetAssetPath(this);
        id = AssetDatabase.AssetPathToGUID(path);
#endif
    }

    public virtual void ActivateAbility(GameObject target, Transform position, Transform firePoint)
    {
        Debug.Log("Activating from Ability");
    }

    public virtual string GetDescription()
    {
        return "";
    }
[CreateAssetMenu(menuName = "Ability2")]
public class OffensiveAbility : Ability
{
    public void ActivateAbility(GameObject target, Transform position, Transform firePoint)
    {
        Debug.Log("Activating from Offensive Ability");
    }

    public string GetDescription()
    {
        return "";
    }
}

Part of code from my slot:

 public Ability Ability
    {
        get => _ability;
        set
        {
            _ability = value;
            _amount = 1;

            if (_ability == null)
            {
                slotIcon.color = disabledColor;
            }
            else
            {
                slotIcon.color = normalColor;
                slotIcon.sprite = _ability.Icon;
            }


        }
    }

You should mark OffensiveAbility.ActivateAbility as override. and same for GetDescription.
Without override you just creating new method that hide base method.

so your OffensiveAbility should looks like this

[CreateAssetMenu(menuName = "Ability2")]
public class OffensiveAbility : Ability
{
    public override void ActivateAbility(GameObject target, Transform position, Transform firePoint)
    {
        Debug.Log("Activating from Offensive Ability");
    }
    public override string GetDescription()
    {
        return "";
    }
}
1 Like

I know i should override it and it was overrided. The problem is that i want to get acces to scriptable object component but it’s hard or even not possible to get so I’ll rebuild a bit my classes.

Please don’t mix terminology. ScriptableObjects are NOT Components. MonoBehaviours are Components. This is why you will NEVER be able to GetComponent<>() on a ScriptableObject.

The “parent” relationship in Unity is only meaningful with the Transform Component, which determines the relationship between different GameObjects, and has absolutely zero meaning with ScriptableObjects.

If you are inheriting a class, use the terminology for inheritance, which is generally base and derived, not “parent and child.”

1 Like

@Kurt-Dekker Sorry for that and thanks for explanation. I did manage to rebuild my ability class and everything works.

The code that you posted did not actually use the keyword “override” when declaring OffensiveAbility.ActivateAbility. (You probably should have gotten a compiler warning about this.)

If you don’t actually say “override” then you get method hiding instead of polymorphism. (The compiler assumes that it’s only a coincidence that the names are the same.)

1 Like