Search code examples
c#unity-game-engineruntimeloadabstract-class

Can I load an abstract class at runtime in Unity?


I'm making a card game where I assign random effects to cards, so I need to load the effect's code at runtime with just the class name.

I don't know if my abstract class and child are done properly, and I also don't exactly know how to get the class needed from a path. I know Resouces.Load won't work but I'll leave it there to convey what I wanna do more easily.

public class GameManager : MonoBehaviour
{

 public Effect effect;

 ...

 effect = Resources.Load<Effect>("Card/Effects/" + c.cardActual.effect1);

                if (effect.Execution())
                {
                    StartCoroutine(TargetAndCastSpell(c,p));
                }

This is the code for my abstract class

    public abstract class Effect : MonoBehaviour
{
    public string targetType;
    public List<int> availableTargets;
    public int effectTier;
    public PlayerHolder playerTarget;
    public CardPhysicalInstance minionTarget;
    public PlayerHolder caster;
    public void EffectX(PlayerHolder PlayerTarget, CardPhysicalInstance MinionTarget)
    {
    }
    public bool Execution()
    {
        return false;
    }

}

And lastly the child I want to load in runtime

 class Spark : Effect
{
    string targetType = "any";
    //Deal 1 damage to any target

    public bool Execution ()
    {
        bool canTarget = false;
        caster = GameManager.singleton.currentPlayer;
        availableTargets = SpellHelper.AvailableTargets();
        if (targetType == "any") //Placeholder check
        {
            canTarget = true;
            caster.playerState = GameManager.PlayerState.targeting;
        }


        return canTarget;

    }

...

Any help is deeply appreciated, thanks and sorry about my clear lack of understanding of abstract classes.


Solution

  • Based on comments, I think Overriding is the Droid you are looking for. With Polymorphy there is two ways different Implementations can be resolved.

    • hiding is possibly by default. However, it is also pretty much useless. It is one of those things we thought we need and now everyone adds it to their OOP language. But aside from not using hiding when I wanted to overwrite, I have never had any use for it.
    • Overriding is the important thing. However, overriding has to be allowed for a function in the base class that first added it.

    In Effect:

    //Stil work how it does, but now can be overridden
    public virtual bool Execution()
    {
        return false;
    }
    

    In Spark:

    //We are actually overriding - not just hiding - Effect.Execution() here
    public override bool Execution ()
    {
        bool canTarget = false;
        caster = GameManager.singleton.currentPlayer;
        availableTargets = SpellHelper.AvailableTargets();
        if (targetType == "any") //Placeholder check
        {
            canTarget = true;
            caster.playerState = GameManager.PlayerState.targeting;
        }
    
    
        return canTarget;
    
    }
    

    You can assign a Spark to a Effect variable, call Execution() and Polymorphy will deal with calling the version of Spark.

    Add anotehr Effect sub-class? As long as it also overrides Execution() it works the same.

    The Effect version could be empty/turned abstract. Or be kept as a default version for all subclasses.

    With hiding you would have to cast it back to Spark to get access to it's variant of the Method. Wich is just extra work with no apparent advantage.