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 /
  • Help Room /
avatar image
0
Question by brendans95 · Apr 13, 2016 at 10:07 AM · c#getcomponentfindfindgameobjectswithtagreference-other-object

Referencing variable from another script on another object

Firstly I'm aware this question has been asked to death, which is why I'm pulling my hair out here with my code - which, according to all the answers I've seen on here, is exactly right to the letter. I've got a public float value on one script that I'm trying to access on another script on another game object but for some reason Unity keeps throwing "Null Reference Exception: Object reference not set to an instance of an object" at me >.<

I have one script on one object that gives me a public float value in the Inspector.

 using UnityEngine;
 using UnityEngine.UI;
 using System.Collections;
 
 public class CurrentHPSender : MonoBehaviour
 {
     public float currentHealth;
 
     void Update()
     {
         Image image = GetComponent<Image>();
         currentHealth = image.fillAmount;
     }
 }

Then I have script on another game object which attempts to access that public float:

 using UnityEngine;
 using UnityEngine.UI;
 using System.Collections;
 
 public class CurrentHPReceiver : MonoBehaviour
 {
     public float HP;
     public GameObject Kirito_Damaged;
     public float Turn_Damaged_At;
     private bool KiritoDamagedSpawned;
 
     void Update()
     {
         GameObject hpbar = GameObject.FindGameObjectWithTag("HPBar");
         CurrentHPSender currenthpsender = hpbar.GetComponent<CurrentHPSender>();
         HP = currenthpsender.currentHealth;
 
         if ((HP <= Turn_Damaged_At) && KiritoDamagedSpawned == false)
         {
             Destroy(gameObject);
             Instantiate(Kirito_Damaged, transform.position, transform.rotation);
             KiritoDamagedSpawned = true;
         }
     }
 }

And it's having an issue with the line

         HP = currenthpsender.currentHealth;

I've tried using different ways of finding the object - GameObject.Find("") for example and nothing changes! Is there something wrong here that I can't see? Please help!

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

3 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by giorashc · Apr 13, 2016 at 10:18 AM

Do not use methods like GetComponent or FindGameObjectWithTag in the Update method as it will impact performance as it is high frequently called.

Do these in Awake()/Start() methods and keep the result in a private member of your script so you could easily access it wherever you need (in that script) without making these costly calls.

After you fix that, keep a reference of the game object with the sender script on the receiver script (via the unity editor) as a public member:

 public class CurrentHPReceiver : MonoBehaviour
  {
      public float HP;
      public GameObject Kirito_Damaged;     
      public float Turn_Damaged_At;
 
      public GameObject hpBarGameObj;
      private CurrentHPSender senderScript;
 
      private bool KiritoDamagedSpawned;
  
      void Awake() {
               senderScript = hpBarGameObj.GetComponent<CurrentHPSender>();
      }
 
      void Update()
      {
          HP = senderScript.currentHealth;
  
          if ((HP <= Turn_Damaged_At) && KiritoDamagedSpawned == false)
          {
              Destroy(gameObject);
              Instantiate(Kirito_Damaged, transform.position, transform.rotation);
              KiritoDamagedSpawned = true;
          }
      }
  }

Use the script order execution (Project Settings) to make sure that the HP bar object is created before objects that use it (such as the receiver obj)

Comment
Add comment · Show 1 · 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 brendans95 · Apr 13, 2016 at 10:29 AM 0
Share

$$anonymous$$an you're a lifesaver! Accessing the hpbar as a public GameObject makes so much more sense. And yeah I'll definitely keep 'get component' and 'getobjectwithtag' commands out of Update - thanks for the advice (I'm fairly new to program$$anonymous$$g :D) Also I had no idea about the Script Order Execution settings so thank you for that!

avatar image
1

Answer by M-Hanssen · Apr 13, 2016 at 10:38 AM

First of all it is very bad practice to execute GetComponent or FindGameObjectWithTag inside the Update method. Please do this on Awake or Start.

I've taken the liberty to modify your script so hopefully it will be clear to you how to do this the proper way. Still FindObjectOfType() should be avoided because it is very inefficient!

 using UnityEngine;
 using UnityEngine.UI;
 
 public class CurrentHPSender : MonoBehaviour
 {
     public float CurrentHealth;
     protected Image Image;
 
     protected void Awake()
     {
         Image = GetComponent<Image>();
     }
 
     protected void Update()
     {
         CurrentHealth = Image.fillAmount;
     }
 }
 
 public class CurrentHPReceiver : MonoBehaviour
 {
     public float Hp;
     public GameObject KiritoDamaged;
     public float TurnDamagedAt;
     protected bool KiritoDamagedSpawned;
     protected CurrentHPSender CurrentHpSender;
 
     protected void Awake()
     {
         CurrentHpSender = FindObjectOfType<CurrentHPSender>();
         Debug.Log("Currenthpsender object is:" + CurrentHpSender);
     }
 
     protected void Update()
     {
         Hp = CurrentHpSender.CurrentHealth;
         if ((Hp <= TurnDamagedAt) && KiritoDamagedSpawned == false)
         {
             Destroy(gameObject);
             Instantiate(KiritoDamaged, transform.position, transform.rotation);
             KiritoDamagedSpawned = true;
         }
     }
 }
Comment
Add comment · Show 1 · 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 brendans95 · Apr 13, 2016 at 11:11 AM 0
Share

Thanks so much! THIS SEE$$anonymous$$S SO $$anonymous$$UCH $$anonymous$$ORE EFFICIENT THAN WHAT I WAS DOING haha I'll definitely keep your advice in $$anonymous$$d for the future and try to be as efficient as possible (I'm quite new to program$$anonymous$$g) - all part of the learning experience so thank you :)

avatar image
1

Answer by xavierwielemans · Apr 13, 2016 at 10:39 AM

Hi guys, I agree with @giorashc, using Find* or GetComponent methods (slow by definition) in Update() is not a good practice. That being said, good news for you @brendans95: no bugs in your scripts! :) I copy-pasted them in a unity project, attached them to 2 new GameObjects (sender and receiver) and tagged the sender with a new HPBar tag. Then I ran my scene and got no error. The exception at line 16 in your script does not mean that Unity can't find the currentHealth public variable in your sender, but rather that your currentHPSender variable is null. And since currentHPSender is where your store the result of your GetComponent() call, it probably means that your hpBar GameObject has no CurrentHPSender script componnent.

i.e. it seems you indeed have at least one gameobject in your scene that has the HPBar tag (otherwise FindGameObjectWithTag would have returned null and you would have had a null ref exception at the previous line, line 15). But that game object has no CurrentHPSender script added to it as a component.

It may also be that you tagged several GO with the HPBar tag and FindGameObjectWithTag returns you another one than the one you expected (and one that has no CurrentHPSender script).

A good old way to check and debug all that is to test the intermediate return values of your code:

 GameObject hpbar = GameObject.FindGameObjectWithTag("HPBar");
 if (hpbar == null) {
     print("ERROR - no hpbar object found!");
 } else {
     print("hpbar object found. Name: " + hpbar.name);
     CurrentHPSender currenthpsender = hpbar.GetComponent<CurrentHPSender>();
     if  (currenthpsender == null) {
         print ("ERROR - no currenthpsender script found on hpbar object!");
     } else {
         HP = currenthpsender.currentHealth;
     }
 }

Hope this helps!

Cheers,

Xavier

Comment
Add comment · Show 1 · 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 brendans95 · Apr 13, 2016 at 11:10 AM 0
Share

Thank you so much! This will definitely come in handy to make sure I'm not doubling up on those tags - and yeah no Find* or GetComponent commands in Update for me from now on! Thanks!

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

129 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

Related Questions

What to use instead of GameObject.Find and GetComponent 2 Answers

Unity GetComponent Script? 1 Answer

Why i can't get Rect Transform 2 Answers

Is it possible to get a component from a parent of a found GameObject? 0 Answers

How to fix "no overload for method get component takes 1 arguments" 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