'How to correctly inherit Unity's callback functions like Awake(), Start() and Update and FixedUpdate()?

I've created a parent class that I expect to have all functions related to testing if the GameObject is grounded, in water, on air, etc... given that this functions will be used by the player as well as other GameObjects. However, the child class seems not to inherit properly the functions.

The parent script it's as follows:

public class CharacterPhysic : MonoBehaviour {
  [SerializeField] protected Transform groundPoints;
  float grounRadius;
  private void Start ()
  {
     whatIsGround = LayerMask.GetMask("Ground");
     groundRadius = 0.01f;
  }
  protected bool IsGrounded()
  {
     Collider2D[] colliders = Physics2D.OverlapCircleAll(groundPoints.position, groundRadius, whatIsGround);
     if (colliders.Length > 0)
     {
         return true;
     }
     else return false;
  }
  private void FixedUpdate()
  {
     Debug.Log(IsGrounded());
  }
}

And the children script is just:

public class ErrantMove : CharacterPhysic {
  private void FixedUpdate()
  {
     Debug.Log(IsGrounded());
  }
}

When added the first script as a component to a Gameobject (after defining the grounPoint) the Debug.Log(IsGrounded()); returns TRUE

However, when added the second script as a component to the same Gameobject (after defining the grounPoint and remove the first script) the Debug.Log(IsGrounded()); returns FALSE even in the same circumstances.

I'm expecting to be able to add movement functions into the second script but this depends on the ability to test if it is grounded.



Solution 1:[1]

Your Start method will not be executed in child class. Move it into child class if you are not going to use parent class.

public class ErrantMove : CharacterPhysic {

  protected void Start ()
  {
     whatIsGround = LayerMask.GetMask("Ground");
     groundRadius = 0.01f;
  }

  private void FixedUpdate()
  {
     Debug.Log(IsGrounded());
  }

}

You can notice that if you will have more than one child classes, you will be forced to initialize base class's Start method in every child class, so you can create an virtual Start method, then call it inside child classes:

public class CharacterPhysic : MonoBehaviour {
  . . .
  protected virtual void Start ()
  {
     whatIsGround = LayerMask.GetMask("Ground");
     groundRadius = 0.01f;
  }
  protected bool IsGrounded()
  {
     Collider2D[] colliders = Physics2D.OverlapCircleAll(groundPoints.position, groundRadius, whatIsGround);
     return colliders.Length > 0;
  }
  . . .
}

public class ErrantMove : CharacterPhysic {

  protected override void Start()
  {
      base.Start();
  }

  private void FixedUpdate()
  {
     Debug.Log(IsGrounded());
  }

}

you can go either virtual/override approach, or use new keyword to "unhide" child class's Start method (I'm not sure how new will behave in unity, so better go with first one).

Solution 2:[2]

You can properly inherit Unity's callback functions such as Awake, Start and Update like you would with a normal C# inheritance paradigm. It's very simply.

Make the all the callback functions for the base class to be virtual:

public class YourBaseClass : MonoBehaviour
{
    protected virtual void Awake()
    {
        Debug.Log("Awake Base");

    }

    protected virtual void Start()
    {
        Debug.Log("Start Base");
    }

    protected virtual void Update()
    {
        Debug.Log("Update Base");
    }

    protected virtual void FixedUpdate()
    {
        Debug.Log("FixedUpdate Base");
    }
}

For the parent class that will derive from the base class, add the callback functions too but mark them as override. If you need the base function to be called, call it with base.FunctionName before doing anything else in the parent function:

public class Parent : YourBaseClass
{
    protected override void Awake()
    {
        base.Awake();
        Debug.Log("Awake Parent");
    }

    protected override void Start()
    {
        base.Start();
        Debug.Log("Start Parent");
    }

    protected override void Update()
    {
        base.Update();
        Debug.Log("Update Parent");
    }

    protected override void FixedUpdate()
    {
        base.FixedUpdate();
        Debug.Log("FixedUpdate Parent");
    }
}

Solution 3:[3]

When tested in Unity version 2020.1.21f, protected callback functions like Start will automatically be executed in their child classes. There is no need to declare a function as virtual, you should only do that if you intend to override the function in a subclass.

public class ParentClass : MonoBehavior
{
    protected void Start()
    {
        Debug.Log("Hello, my class is ");
        Debug.Log(this.GetType());
    }
}

public class ChildClass : ParentClass
{
    //empty class
}

public class GameManager : MonoBehavior
{
    //childPrefab is a prefab containing the ChildClass script as a component
    Object.Instantiate(childPrefab);
}

Upon instantiating the childPrefab containing the ChildClass script, the object will print, "Hello, my class is ChildClass".

As for your example, the only thing you would need to do to fix that code is change your Start function to protected. That will ensure that Start is inherited by ErrantMove. Additionally, if you don't intend to use FixedUpdate for anything other than checking IsGrounded(), you could mark FixedUpdate as protected, and then delete it from your subclass.

If you want to add additional functionality to FixedUpdate in your subclass, then you will need follow the advice of the other answerers and use virtual, override, and base.FixedUpdate().

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
Solution 2 Programmer
Solution 3 sandsalamand