Base.Method using Base classes variables instead of new variables in Inherited Class

I am currently dealing with an issue that alludes me, below is a example version of the problematic code

public class Base : ScriptableObject
{
     public float Var1 = 0f;
     public virtual void PrintVar()
     {
          Debug.Log(Var1);
     }
}
public class Child1: Base
{
     public new float Var1 = 2f;
     public override void PrintVar()
     {
          base.PrintVar();
     }
}
public class Caller : MonoBehaviour
{
     public Base AssignedScript;
     void OnStart()
     {
          AssignedScript = ScriptableObject.CreateInstance("Child1");
     }
     void OnUpdate()
     {
          AssignedScript.PrintVar();
     }
}

I have class that can hold Base and any scripts that inherit from it, but when I call PrintVar() from any of those children, it only seems to use Var1 from the Base script, and not Var1 from the child that PrintVar() was called from. I would expect that:


Child1.PrintVar() would print 2, but instead it prints 0.


Is there something I am doing wrong?

Hi!

Unfortunately you cannot directly override fields in this way, however, you are able to override the accessors of a field. So if all you cared about was overriding the default value, you could try this (simplified):

public class Base 
{
    public virtual float Var1 { get; set; } = 1f;
}
public class Child : Base
{
    public override float Var1 { get; set; } = 2f;
}

//elsewhere
Base AssignedScript = new Base();
AssignedScript.PrintVar(); //Output: 1

AssignedScript = new Child();
AssignedScript.PrintVar(); //Output: 2

However, giving a field into an accessor like this no longer shows it in the inspector (unity is rightfully scared that the act of displaying it will change the variable).

If you are using scriptable objects, you probably need to change the fields in the inspector, so you can try a bit of a hybrid approach (simplified):

public class Base
{
    [SerializeField] private float baseVar = 1f;
    public virtual float Var1 { get => baseVar; set => baseVar = value; }   
}
public class Child : Base
{
    [SerializeField] private float childVar = 2f;
    public override float Var1 { get => childVar; set => childVar = value; }
}

Doing this allows unity to display the field without worrying, and allows you to override the default value while retaining the lovely inheritance hierarchy.

(Other ways to implement something like this: c# - Overriding fields or properties in subclasses - Stack Overflow )

Hope this helps! :smiley: