How to properly reference a game object
If I attempt to assign a GameObject to a private variable in Start() or Awake() then access that object I get NullReferenceException.
But if I make it public and assign it via inspector it works fine. What am I doing wrong?
This works if drag and drop the game object into myObject via the inspector.
using UnityEngine;
using System.Collections;
public class ChangeControls : MonoBehaviour {
public GameObject myObject;
void ChangeMyObject()
{
myObject.SomeValue = 42;
}
}
This however does not work.
using UnityEngine;
using System.Collections;
public class ChangeControls : MonoBehaviour {
private GameObject myObject;
void Start()
{
myObject = GameObject.Find("My Object");
}
void ChangeMyObject()
{
myObject.SomeValue = 42;
}
}
I assume by GetObject.Find
you mean GameObject.Find
?
Do you have an object in your hierarchy named $$anonymous$$y Object? Is it active/enabled?
$$anonymous$$y apologies, you are correct. I fixed it. And yes there is an object called "$$anonymous$$y Object" and it is active/enabled.
Answer by calebaker · Aug 28, 2015 at 08:29 PM
I ended up scrapping the script and created a new one from scratch and now it works.
The only thing I can come up with is something (a reference) had to be corrupted in Unity because the new script exactly matches the old one.
@calebaker That's odd, but it would make the most sense being that all of the likely certainties were ruled out! I even reproduced your setup earlier today and found no issues getting the code to work as intended.
Answer by Mako-Infused · Aug 27, 2015 at 08:34 PM
There's a chance that the line:
myObject = GameObject.Find("My Object");
Is not finding the object. In which case it would be null, of course that can be prevented by using a null check when assigning values.
Additionally, I would try moving your find of the object into an "Awake" method instead of "Start". This is necessary if your "ChangeMyObject()" method is being invoked before the value is assigned.
As mentioned in my original post, I have attempted Awake() but I get the same result.
I don't believe proper prevention of an error is to just not do the thing that would cause the error in the first place but ins$$anonymous$$d to do it correctly by fixing what caused the error.
Awake is called on all objects first before Start, Execution Order from the docs. If you put it in the Awake function you have no guarantee(with out modifications) that the object has been initialized. Where as in the Start method you know Awake was called on everything in the scene that can have it called. The Start method is more appropriate.
$$anonymous$$y apologies, I didn't realize that you mentioned using Start and Awake. Awake should definitely be the more correct implementation, considering that you're linking an object to a variable.
I didn't mean to imply that it would prevent the error, rather that you should really consider adding in a null check when working with "GameObject.Find" since names aren't static. As a bonus this approach might also help you debug the problem yourself. However, it really depends on your implementation.
The problem is definitely that the component doesn't exist at the time "Change$$anonymous$$yObject" is called, which narrows down the possible reasons for that to: the name is wrong, or the ti$$anonymous$$g is wrong. The only other possible reason for the issue might be due to the "SomeValue" not referencing the component which contains that value, in which case a cast might be needed.
@$$anonymous$$ako
No worries, the idea of a null check is a solid one. I attempted once again to place it in Awake but I'm getting the same result. I have verified and had a coworker verify that the na$$anonymous$$g is correct.
I'm wondering now if something has gotten corrupted in the scene/unity editor?
Remember to keep in $$anonymous$$d that when this object is assigned in the inspector I am able to modify SomeValue.
Answer by Barachiel · Aug 28, 2015 at 03:38 PM
Quickly testing this out, using this script:
using UnityEngine;
using System.Collections;
public class ChangeControls : MonoBehaviour
{
private GameObject myObject;
void Start()
{
myObject = GameObject.Find("My Object");
if(myObject != null)
{
ChangeMyObject();
}
}
void ChangeMyObject()
{
Debug.Log("Found!");
}
}
No errors are returned and it works fine. This suggests that it's something else in your script, perhaps 'myObject.SomeValue'.
Since it works fine if you assign it via inspector, perhaps you could explain more about what this value is, since in the code provided it makes no sense.