Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Access float variable from another script

Discussion in 'Scripting' started by schwooba, Sep 21, 2017.

  1. schwooba

    schwooba

    Joined:
    Nov 25, 2013
    Posts:
    33
    Having problems figuring out how to grab a variable from another script. It seems so easy but I'm not getting it. I'm trying to get the Motor public float health variable. Any help would be appreciated.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. namespace 123
    6. {
    7.     public class Motor : MonoBehaviour(
    8.         public float health = 1;
    9. ...
    10.  
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4. using UnityEngine.SceneManagement;
    5.  
    6. namespace 123
    7. {
    8.     public class Health : MonoBehaviour
    9.     {
    10.         private Motor MotorHealth;
    11.         void Awake()
    12.         {
    13.           Motor MotorHealth = GetComponent<Motor>();
    14.             Debug.Log("The Player Health is" + MotorHealth.health);
    15. ...
    I'm trying to get the health value from the Motor script but Debug says "Object reference not set to an instance of an object" :/

    Thanks.
     
  2. Rob21894

    Rob21894

    Joined:
    Nov 21, 2013
    Posts:
    309
    If you're not heaving more than one Instance/Gameobject that Has the motor script attached then you can do this

    Code (CSharp):
    1. namespace 123
    2. {
    3.     public class Health : MonoBehaviour
    4.     {
    5.         private Motor MotorHealth;
    6.         void Awake()
    7.         {
    8.             MotorHealth = GameObject.FindObjectOfType<Motor>(); // if on different object
    9.             MotorHealth = GetComponent<Motor>(); // if on same object
    10.             Debug.Log("The Player Health is" + MotorHealth.health);

    Note: You didn't need to Re instance Motor in the Awake Function as you already had it declared as a private above.

    EDIT: Another way you can do this is if you make the private variable public and drag the script into the variable in inspector, they you wont have to use
    Code (CSharp):
    1.            MotorHealth = GameObject.FindObjectOfType<Motor>();
     
    Last edited: Sep 21, 2017
    parkdark1845 likes this.
  3. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    GetComponent<TComponent> looks for components attached to the GO that the method is called for. In your case, it's the object that your health script is attached to.
    In your particular situation this is not the case, as the call to GetComponent<Motor>() does not find an instance of the component type.

    Either ensure you've attached this to the same gameobject or that you reference the corresponding gameObject that holds your motor script instance.
    Note that you can also assign UnityObjects (GOs, Components, etc) via the inspector in order, if that fits your needs.

    Also, you declared a new local variable that does not represent the member variable of the class, so an assigment to your member variable does not take place.

    Another tip: I'd inverse the dependency if you need the relation between these types at all. Make the motor access the Health component and not the other way around, as you can then re-use the health component.
     
    Stardog likes this.
  4. kikendo

    kikendo

    Joined:
    Jul 19, 2017
    Posts:
    61
    Would a static solve your problem?
    Code (CSharp):
    1.  
    2. public class Motor : MonoBehaviour {
    3.     public static float health = 1;
    4. }
    5.  
    Code (CSharp):
    1.  
    2. public class Health : MonoBehaviour {
    3.     void Awake() {
    4.     Debug.Log("The Player Health is" + Motor.health);
    5.     }
    6. }
    7.  
     
    M7mdAsd likes this.
  5. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Please don't do that... That only introduces lots of other problems and is not a reasonable choice from the perspective of architecture and it also does not represent an instance's state.
     
  6. kikendo

    kikendo

    Joined:
    Jul 19, 2017
    Posts:
    61
    Can you explain more? I'm new to Unity and would like to understand why I shouldn't do that. Also what problems it could introduce.
     
  7. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Statics are used to declare members (fields, properties, methods, and so on) on the declaring type's level. That is, you don't even need an instance to access that state, it's given by the existence (to be exact initial (static) initialization) of the type itself. If you have instances of that type, they all share that one single member.

    You can illustrate this by the following example:
    Your car has a motor. My car has a motor. If both rely on an attribute 'hitpoints' that's only ever defined once for 'Motors', your motor will be broken as soon as my motor is broken. And vice versa.

    From the perspective of software engineering, and especially Object Oriented Programming (OOP), this is considered a flaw in design.

    The 'health' members needs to exist per instance, no matter if it's a primitive type or a complex type.

    There are other implications as well, for example in regards to inheritence, abstractions and dependencies and this all bubbles up to the general discussion about software architecture and design. But in order to get a hang on it, it's important to understand what static are really used for, and what they're defintely not used for.
    Of course there're always situation in which you could go 'static', but it's always worth the effort thinking about an alternative, more flexible way.
     
    Last edited: Sep 21, 2017
  8. kikendo

    kikendo

    Joined:
    Jul 19, 2017
    Posts:
    61
    Oh I see what you mean, yes.
    Again I don't know details of how the OP wants to use this, my method would work ONLY if there was only one instance of Motor ever, right? MY assumption of his use was wrong.

    I guess by him trying to define a type Motor, that he wants to have different motors and static would not work out. Cool, thanks for explaining. I'm rusty with all the oop stuff, I learned (and forgot it) eons ago.
     
  9. schwooba

    schwooba

    Joined:
    Nov 25, 2013
    Posts:
    33
    Thanks for the suggestions. I'll try it out later today.
     
  10. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    It technically would work for one instance, but there are various ways to solve this problem without static members. Instead, the most commonly seen here on forums are Singletons, but they also introduce their own tradeoffs...
    Singleton basically means you declare the type with members on the instance level, and in the end, only ever allow one instance to exist.
    It's much better than going static all the way, but as mentioned, it brings its own tradeoffs.

    More advanced are systems and containers that provide instances for you and instantiate them when needed. They can 'act' as many different kinds of instance providers, let it be singletons, multitons, pooled objects and the like.
    If you're interested in an overkill (but very flexible!) solution once you refreshed all your knowledge, you can have a look at dependency injection and inversion of control with type- or contextual bindings.

    Of course, you do not always need that level of complexity.
     
    kikendo likes this.