- Home /
FindWithTag is returing true, and while GetComponent is returning null...seemly random
I have a boss prefab with a script that my GUI's Script calls on to display its health. My boss's script calls my GUIScript.UpdateBossShowBar on awake (which works).
bossHealthControllerObject is returning my boss prefab, but bossHealthController is returning null, but not every time. Sometimes it returns null, sometimes it finds my script.
Not sure if this helps, but it gets more confusing: I temporarily put UpdateBossShowBar (); into Update so it gets called every frame (for testing proposes), and I found the Null error fixes itself if I click anywhere in the Hierarchy or Project menus while UpdateBossShowBar is being called.
public void UpdateBossShowBar ()
{
//Find the BossHealthController script
GameObject bossHealthControllerObject = GameObject.FindWithTag ("Boss");
if (bossHealthControllerObject != null)
{
bossHealthController = bossHealthControllerObject.GetComponent <BossHealthController>();
Debug.Log (bossHealthControllerObject);
Debug.Log (bossHealthController);
}
if (bossHealthController == null)
{
Debug.Log ("Cannot find 'BossHealthController' script");
}
}
Been searching answers and other sites for this all day, and can't find any solution.
Did you say that UpdateBossShowBar() is being called from OnGUI()? That's a bad idea - OnGUI runs multiple times per frame. Why don't you move your FindWithTag and GetComponent calls to, e.g., the Start() function, and then just cache a reference to them to re-use in this function?
e.g.
GameObject bossHealthControllerObject;
BossHealthController bossHealthController;
void Start() {
GameObject bossHealthControllerObject = GameObject.FindWithTag ("Boss");
if (bossHealthControllerObject != null)
{
bossHealthController = bossHealthControllerObject.GetComponent <BossHealthController>();
}
}
void UpdateBossShowBar ()
{
// do stuff with bossHealthControllerObject and bossHealthController
}
Fairly new to C# and Unity, I do not know what you mean by cache a reference.
I tried putting my GamveObject.FindWithTag and GetComponent in the start loop, but then it only works if I have the GameObject with the Boss tag in the starting frame, and doesn't work as an instantiated prefab.
Answer by Bunny83 · Jul 06, 2014 at 06:43 AM
You have to start to properly debug. First of all it makes no sense to Debug.Log multiple values without a reference. Use a distinguishable text. Next thing is it looks like the "bossHealthController" variable is declared in the class itself. Are you sure you don't have any other code that might set / replace the content of that variables?
It might be a good idea to temporarily make "bossHealthControllerObject" and "bossHealthController" a public member variable. That way you can see in the inspector which is found and you can double click on it to see "what" it actually found. Maybe you have other things tagged with "Boss"?
public GameObject bossHealthControllerObject;
public BossHealthController bossHealthController;
public void UpdateBossShowBar ()
{
bossHealthControllerObject = GameObject.FindWithTag ("Boss");
if (bossHealthControllerObject != null)
{
bossHealthController = bossHealthControllerObject.GetComponent <BossHealthController>();
if (bossHealthController == null)
{
Debug.LogWarning("The first gameobject tagged 'Boss' doesn't have a 'BossHealthController'");
}
else
{
Debug.Log("Everything ok, got 'BossHealthController'");
}
}
else
{
Debug.Log ("Cannot find a gameobject tagged 'Boss' ");
}
}
Use that and see what output you get. Also at runtime check the two variables in the inspector to see their content.
ps: If that's actually all you do in "UpdateBossShowBar" it really should have a name like
void FindBoss()
since it doesn't update the boss nor any gui bars. All it does is getting a reference to the "next" BossHealthController.
I reorganized my script like you said with debugs that are more readable, and got the "The first gameobject tagged 'Boss' doesn't have a 'BossHealthController'" message (nothing new learned here, outside of better practices anyway).
I do have some things in the one else loop though, so it does have a function (enabling the GUI health bar):
Debug.Log("Everything ok, got 'BossHealthController'");
//Show bar
bossHealth.enabled = true;
bossText.enabled = true;
UpdateBossHealth ();
Well, have you checked what object is referenced by "bossHealthControllerObject"? Just double click it in the inspector. Are you sure that the object which is selected has a "BossHealthController" script attached? Because when GetComponent returns null, you can be sure that there is no such component.
Program$$anonymous$$g is a very exact science. Either you do something wrong or you don't understand what you're doing wrong ;)
I bet you have another object tagged "Boss" which doesn't have a BossHealthController script attached. $$anonymous$$aybe a child object of your Boss prefab?
You gave me an idea. I made bossHealthControllerObject public, and found the reference in editor goes "missing" (ins$$anonymous$$d of "None", which would be if nothing was found). The gameobject and script are there and haven't been deleted.
Answer by Bunny83 · Jul 07, 2014 at 02:37 AM
Well, if the reference is "missing" then it's most likely has been destroyed.
Try adding an OnDestroy callback to your "BossHealthController"
void OnDestroy()
{
Debug.Log("BossHealthController destroyed");
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
UnityEngine Assert IsNotNull not working on empty inspector field 1 Answer
Does pattern matching verify object lifetime and null references 1 Answer
"NullReferenceException: Object reference not set to an instance of an object" with instantiate C# 1 Answer