Using inheritance with scripts attached to different gameobjects : Base class Awake called multiple time, normal ?

Hi guys,
I’m currently trying to manipulate and understand inheritance in unity.

In my scene lets say we have a parent game object called Example and a child game object called Example Child.

In the parent i put a script like :

public class Example : MonoBehaviour
{
	private void Awake()
	{
		Debug.Log("Example : " + transform.name);
	}
}

In the child :

public class ExampleSub : Example
{
	private void Awake()
	{
		Debug.Log("ExampleSub : " + transform.name);
	}
}

Results in the console will be :

Example : Example

ExampleSub : Example Child

Now lets say we do this :

In the parent i put the same script :

public class Example : MonoBehaviour
{
	private void Awake()
	{
		Debug.Log("Example : " + transform.name);
	}
}

In the Child :

public class ExampleSub : Example
{
       // No awake function
}

Results in the console will be :

Example : Example

Example : Example Child

The way I understand this behavior is :

  • Example gameobject call attached Example Script which call Awake function
  • Example Child gameobject call attached ExampleSub Script which
    call Awake from Example Script base class.

The problem is : if I don’t call an awake in the subclass, it will repeat all the code in the Awake from the base class. But I don’t need all the stuff in the awake base class for my subclass. I will just need some variables from the base, but not to do all of its awake operations…
The solution I found is to call an empty awake in the subclass. This way, the subclass doesn’t execute the awake from the base class. But I don’t know if it’s a good practice… That seems a weird behavior. Does it exists any other option ?

I hope I’m clear in my explanations ^^

Hi!

Thank you for very good description of you issue. The solution for your desired behaviour can be virtual classes. Take a look at these lines of codes:

public class Example : MonoBehaviour
{
    public virtual void Awake()
    {
        Debug.Log("Example : " + transform.name);
    }
}

And the Child:

public class ExampleSub : Example
{
    public override void Awake()
    {
        // base.Awake(); If you want to execute child code then simply use base.FunctionName(), if no just remove it
    }
}

This will result in the Console single:

  • Example : parent

The thing with Virtual methods that you declare your base implementation of function, but when you inherit class you can override the function either to add something or to re-implement function completely. In order to execute base implementation of function use base.FunctionName();

IMPORTANT: For functions to be virtual they MUST be public. You cannot declare virtual private function.


Another option is abstract classes:

public abstract class Example : MonoBehaviour
{
    public abstract void Awake();
}

And the Child:

public class ExampleSub : Example
{
    public override void Awake()
    {
        Debug.Log("You MUST have override, otherwise will throw an error");
    }
}

The abstract functions same as virtual MUST be public - they cannot be private.
The difference between abstract and virtual:

  • You can declare virtual function in your usual class, but abstract function requires the class to be abstract as well;
  • Abstract functions don’t have base implementation like virtual therefore when you inherit abstract class you MUST override functions - it will throw an error if you forget to override some function.

Just to clarify - what you described is expected behaviour, because you inherit functions that has base implementations and therefore they being called when your child class inherit them.


Hope that helps.

Hey @ADiSiN , thank you very much for your time and your explanations.
Just to clarify, is it the same to do :

public class ExampleSub : Example
{
    public override void Awake()
    {
        // Nothing
    }
}

and to do (with a non virtual private base class) :

public class ExampleSub : Example
{
    private void Awake()
    {
        // Nothing
    }
}

If I want to do nothing in the Awake subclass, it seems the same to me and no needs to implement a virtual function in the base class ?