Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved Protected variables, derived from a parent class, are empty in child class? (inheritance)

Discussion in 'Scripting' started by tfishell, Jul 1, 2020.

  1. tfishell

    tfishell

    Joined:
    Nov 20, 2017
    Posts:
    97
    This is just something I'm curious about. (sorry if I don't use all the appropriate technical terms)

    In a parent class, I have a method that compares some float and Vector2 positions/amounts (set in the Awake method, aside from transform.position and mouse position/mousePos) in world space to see if the mouse is outside a certain area (IsMouseOutsideDeadzone(), returning true or false). This works fine in the parent class.

    I have a child class which inherits from the parent class. In this child class I can access the inherited variables and methods - "horzExtent", "deadzoneHalves", IsMouseOutsideDeadzone() method, etc.
    However, inside the child class, the float and Vector2 variables (which, in the parent class, had values applied to them) are set to 0. I have access to the variable names+types inside the child class but not the amounts set in the parent class. (The exceptions are transform.position and mousePos mentioned above; mousePos is running in the parent class' Update method edit: mousePos is static, I forgot)

    To be more specific, in the parent class, IsMouseOutsideDeadzone() compares mousePos to a transform.position x and y values + or - deadzoneXHalf or deadzoneYHalf. When calling IsMouseOutsideDeadzone in Update in the parent class, I get what I'm expecting; however when calling IsMouseOutsideDeadzone in the child class, while transform.position and mousePos return the right amounts, all the variables created in the parent class set in Awake return 0.

    Code (CSharp):
    1. //PARENT class
    2.  
    3. protected float horzExtent, vertExtent;
    4.     protected Vector2 cameraBoundsSize, deadzoneBoundsSize;
    5.     protected Vector2 deadzoneHalves;
    6.  
    7.     ...
    8.  
    9.         void Awake()
    10.     {
    11.  
    12.         //get the extents (half the vert and horiz cam sizes)
    13.         horzExtent = Camera.main.orthographicSize * Screen.width / Screen.height;
    14.         vertExtent = Camera.main.orthographicSize;
    15.  
    16.         //store the bounds of the camera (extents * 2)
    17.         cameraBoundsSize = new Vector2(horzExtent * 2, vertExtent * 2);
    18.  
    19.         //create the deadzone size
    20.         deadzoneBoundsSize = new Vector2(horzExtent, vertExtent);
    21.         deadzoneHalves = new Vector2(horzExtent / 2, vertExtent / 2);
    22.     }
    23.      
    24.  
    25.     void Update () {
    26.         //get mouse pos
    27.         mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    28.      
    29.         //if mouse is outside the deadzone areas of the camera
    30.         if (IsMouseOutsideDeadzone())
    31.         {
    32.             //do stuff
    33.         }
    34.     }
    35.  
    36.     protected bool IsMouseOutsideDeadzone()
    37.     {
    38.         float tranPosX = transform.position.x;
    39.         float tranPosY = transform.position.y;
    40.         float deadzoneXHalf = deadzoneHalves.x;
    41.         float deadzoneYHalf = deadzoneHalves.y;
    42.      
    43.         //if mouse is outside deadzone
    44.         if (mousePos.x > tranPosX + deadzoneXHalf || mousePos.x < tranPosX - deadzoneXHalf ||
    45.             mousePos.y > tranPosY + deadzoneYHalf || mousePos.y < tranPosY - deadzoneYHalf)
    46.         {
    47.             //Debug.Log("mouse is outside deadzone");
    48.             return true;
    49.         }
    50.  
    51.         return false;
    52.     }
    53.  
    54.     ---------
    55.  
    56.     //CHILD class, inheriting from parent
    57.  
    58.     void Start()
    59.     {
    60.         Debug.Log(transform.position); //gets camera transform position
    61.  
    62.         //the following all return "0", unlike in the parent class
    63.         Debug.Log("horzExtent: " + horzExtent);
    64.         Debug.Log("deadzoneHalves: " + deadzoneHalves);
    65.         Debug.Log("camBoundsSize: " + cameraBoundsSize);
    66.     }
    67.  
    68.     // Update is called once per frame
    69.     void Update () {
    70.          Debug.Log("MOUSE: " + mousePos); //DOES return the mouse position in world space, like in the parent class
    71.  
    72.         //if mouse is outside deadzone, get the amount it is outside deadzone, and use that as amount to move
    73.         SmoothDampToMousePos();
    74.     }
    75.  
    76.     void SmoothDampToMousePos()
    77.     {
    78.         //unlike in the parent class, here basically always returns "true" because all deadzone values are "0"/there is no area where the mouse is not recognized
    79.         if (IsMouseOutsideDeadzone())
    80.         {
    81.             Debug.Log("outside deadzone, do stuff");
    82.         }
    I assume this is standard behavior and has to do with child classes inheriting the associated variable names + types of the parent variables, but not their respective values (after the equal sign) set in the parent class; or something like that (objects/instances/OOP? are value vs reference types involved here? :p). I figured I'd ask about it.

    (I don't think I'll be using inheritance here, doesn't seem quite right for what I'm doing anyway). Thanks for any further info in advance.
     
    Last edited: Jul 1, 2020
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Variables values are related to an instance of a class, not to the class itself, so they couldn't possibly be inherited. You could have 10 instances of the parent class that all have different values for the same variables. Or zero instances of the parent class.

    But what you should be asking about is the Awake() function, not the variables. The question is whether that function gets executed. If it does, then it will set the variables however it sets them.

    When you are creating a MonoBehaviour that you intend to subclass, you usually want to declare magic methods like Awake, Start, or Update as "protected virtual". That means the subclass will have the same method by default, but also has the option to override the function to do something different if it wants. It also means the subclass can explicitly call the parent class's version of the function by saying something like "base.Awake()".

    If you defined a new Awake function in the subclass, and you didn't call base.Awake, then that will definitely keep the parent's version from running.

    But if you made the parent's version private and didn't define a new one in the child, I'm not sure offhand what happens. The normal C# way of doing these methods would have been for the original MonoBehaviour class to declare them as virtual and let you override them in your own classes. But Unity chose to break the normal C# rules and do their own wacky magical thing instead.
     
    tfishell likes this.
  3. tfishell

    tfishell

    Joined:
    Nov 20, 2017
    Posts:
    97
    Thanks. I played around with this in Unity this morning. (previously followed a Brackeys video on Inheritance, and another channel's one about virtual+overriding but the info didn't really stick since I haven't done much with the subject.) I think I'm sort of "removed" from explicitly creating instances since I've rarely created my own objects via "= new MyOwnType();" in Unity (but have done that in C# study using Visual Studio alone).