Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by ludwu · May 12, 2020 at 11:59 PM · gameobjectparentchildinheritanceawake

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 ^^

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by ADiSiN · May 13, 2020 at 12:42 AM

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.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by ludwu · May 13, 2020 at 01:15 PM

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 ?

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ADiSiN · May 13, 2020 at 01:53 PM 0
Share

Hi!

In Awake() case - yes, but only because it's built-in $$anonymous$$onobehaviour function and let's say Unity does this thing behind for you, not the same way, but it understands which one stays above another and prioritizes it and that's ok if you want to do it, but keep in $$anonymous$$d that this will not work with custom functions.


Here is code that will help you understand it's better and here is link for console output (it won't let me attach picture, sorry for link): https://imgur.com/7YjuP7L

Parent code:

 public class Parent : $$anonymous$$onoBehaviour
 {
     private void Awake()
     {
         Debug.Log("Parent says Awake!");
         CustomFunction();
         CustomVirtualFunction();
     }
 
     private void Start()
     {
         Debug.Log("Parent says Start!");
     }
 
     void CustomFunction()
     {
         Debug.Log("Parent says Custom Function!");
     }
 
     public virtual void CustomVirtualFunction()
     {
         Debug.Log("Parent says Virtual Custom Function!");
     }
 }

Child code:

 public class Child : Parent
 {
     void Start()
     {
         Debug.Log("Child says Start!");
         CustomFunction();
         CustomVirtualFunction();
     }
 
     void CustomFunction()
     {
         Debug.Log("Child says Custom Function!");
     }
 
     public override void CustomVirtualFunction()
     {
         Debug.Log("Child says Virtual Custom Function!");
     }
 }



What we can see:

  • Awake called from Parent since we didn't call it in Child;

  • Start called from Child since we call it and Unity got it that we want it to be called here, not from inherited Parent;

  • Both Parent and Child called Custom Function, because we declared them in both functions and Unity don't see connection between them to check for pointer execution (early binding decided at compile time);

  • Both Parent and Child called Virtual Custom Function, because we called them in both functions, but both of the calls end up using Child implementation that's because virtual functions got us late binding when the implementation of the method gets decided at run time.

avatar image ADiSiN ADiSiN · May 13, 2020 at 02:06 PM 0
Share

To expand a little bit more imagine you have this script:

 public class Aunt : $$anonymous$$onoBehaviour
 {
     public Parent parent;
 
     private void Update()
     {
         if (Input.GetKeyDown(KeyCode.C))
             parent.CustomFunction();
 
         if (Input.GetKeyDown(KeyCode.K))
             parent.CustomVirtualFunction();
     }
 }

You cache in Parent parent reference to the Child that inherit from Parent.

Now, when you press C you will receive: Parent says Custom Function!

However, when you press K you will receive: Child says Virtual Custom Function!


So this become handy when you have multiple objects that should have different implementation of the same function but since the checking for each class name will be too heavy you can call the virtual Function from their inherited function and Unity will point to the overrided execution (if exists, of course).

Hope this was clear enough x)

avatar image ludwu ADiSiN · May 13, 2020 at 04:10 PM 0
Share

I have not the same behavior than you.

That's the result I got in my log console : https://imgur.com/8U9PO13
To be clear, I just added the transform name and see how it acts in monobehavior : https://imgur.com/7fntWf4

  • As we can see, mono first treat the child script that even though it has no Awake function, go through its inherited parent and execute Awake a first time (that's why we have the child virtual custom func logged).

  • It then execute the Parent Awake

  • And then the Child Start

  • And finally the Parent Start

    The problem is : if you don't do anything in child on awake or start, it will still execute the awake and start from the parent. It seems awkward because if you have multiple children of the parent with no awake functions, they will all execute the awake or start of the parent. Lets say there are some heavy operations in awake or start, it could be a problem.
    Plus, if you have something like "transform.Find("someGameObject").getComponent()", children will result in a null reference because they have not the same hierarchy.

    The only option I found is to break this behavior with an empty awake and start in chidren (override or not).
    I'm also asking myself why it is the child script that is first executed by monobehavior over the parent ?

avatar image ADiSiN ludwu · May 13, 2020 at 04:31 PM 1
Share

You have the same bahavior as $$anonymous$$e, but you put Parent in the scene as well, while I am not, that's why you have additional 4 lines of Debug, and that's expected, because by placing Parent in the scene it will call his own functions.

Yes, but you can look at this from another angle: if I wrote my functions in my parent class, why would I want to call them again to execute in my child class? You can create second parent and inherit from the first one where you empties Awake and then no further Child of Second Parent will need to do it, but Child of First Parent will need.


And I don't get what do you mean by Find function - If you place Child object with Inherited Parent class and call FindObjectOfType< Parent>().GetComponent< Collider>() or any kind of that - it will return you Collider of GameObject that contains Children class on itself.

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

207 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Properly Rotating Child Objects by Script 1 Answer

Make a simple tree 1 Answer

"Center On Children" programmatically 1 Answer

Attaching a game object as a child during runtime? 3 Answers

Multiple cameras as child or assign coords/rot to main cam 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges