Search Unity

Monobehaviour inheritance and Awake,Start, OnEnable... etc

Discussion in 'Scripting' started by gdbjohnson, Feb 26, 2015.

  1. gdbjohnson

    gdbjohnson

    Joined:
    Dec 16, 2014
    Posts:
    40
    I ran into a painful issue today, painful due to the obviousness of the issue. I have some objects inherited from one another, extending Monobehaviour. In each of them, I have Awake and Start, and couldn't understand why my Awake method in my base class was only being called intermittently.

    It turns out that an extending class had hidden the base class's Awake method, and consequently, the calls were not being cascaded down my hierarchy as I needed them to. Indeed, it's always been a bit weird to me that declaring `void Awake()` in a Monobehaviour gets called somehow, codemagically, and that I can change the declaration of Awake to be `protected virtual` without issue. Reminds me of Objective-C with loose coupling of messages sent to objects.

    Regardless of those mechanics, I am mostly wondering at this point why I don't see more/any examples on forums / blogs where Awake is declared protected and virtual (C#). Surely polymorphism is being used prevalently in the community, requiring this? Am I missing something?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    declaring a simple method as such:

    Code (csharp):
    1.  
    2. void Awake()
    3. {
    4. }
    5.  
    defaults as a private method. And private members can have the same name as private members in a base class because the scope of private is to the class itself.

    Unity extracts the methods from a component to receive a message by using reflection. Reflection will search starting at the bottom and searching through base classes until it finds the member in name.

    This will result in what appears as the base classes method getting 'overwritten'... though really it's just that they're 2 distinctly different members, and reflection finds the lowest on first.



    I have a base class 'SPComponent' that all my scripts inherit from (because MonoBehaviour isn't enough for me). I have all these methods declard protected virtual, just like you discovered.

    As for tutorials not bringing this up... that I'm not surprised by. Really most tutorials I find avoid inheritance for the most part and deal with adhoc scripts to solve problems. The more advanced stuff often uses compositing to add behaviour to something and avoid inheritance.
     
    SolidAlloy likes this.
  3. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    I still don't like the magic in those calls, especially if you consider that they are frequently the cause for avoidable issues, that would require no debugging and could lead to compilation errors instead that are trivial to resolve.

    But the answer to your question is relatively simple in my opinion:
    protected virtual is only needed if a subclass has to override it. As this is usually not necessary, you barely see it.
     
    gdbjohnson likes this.
  4. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Unity themselves have admitted that the "magic" of calling the Monobehaviour methods through reflection string names instead of inheritance was a bad idea, and their new code (like the new UI) uses interfaces and virtual methods instead. But yeah, for now, if you have subclasses of subclasses of MonoBehaviour, you need to make sure you declare all the MonoBehaviour methods as virtual to avoid headaches down the road.
     
    neonblitzer likes this.
  5. gdbjohnson

    gdbjohnson

    Joined:
    Dec 16, 2014
    Posts:
    40
    @lordofduct Just to be clear, your SPComponent inherits from MonoBehaviour?

    Thanks for the discussion on this.
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
  7. Timelog

    Timelog

    Joined:
    Nov 22, 2014
    Posts:
    528
    So just to get it straight, you CAN declare the Unity methods as virtual and override the usage of them without problems? Or am I missing something?

    I'd swear I heard you can't override those methods if you use them in a base class, due to the way Unity uses reflection :eek:
     
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    nah, you can override them just fine
     
    Timelog likes this.
  9. honprovet

    honprovet

    Joined:
    Mar 4, 2014
    Posts:
    23
    You can override and also use the one in base class by base.Awake() or so, if desired.
     
    hecker_de likes this.