- Home /
C# Null Object Reference - Driving me mad!
Hi there, I'm getting the above error, the object reference is not set to an instance of an object, and I seriously cannot find the reason for it. Here, I'll break it down.
I have my main character script trying to access an inventory script in the Start() function:
Inventory inventory;
GameObject InventoryGUI;
//Start()...
InventoryGUI = GameObject.FindGameObjectWithTag("Inventory GUI");
inventory = InventoryGUI.GetComponent<Inventory>();
Later in the script I try to call the PickUpItem() function from the inventory script:
if (Input.GetKeyDown(KeyCode.F))
{
Ray ray = playerCam.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hitinfo;
Debug.DrawRay(ray.origin, ray.direction * 2, Color.yellow);
if (Physics.Raycast(ray, out hitinfo, 2f))
{
if (hitinfo.collider.gameObject.tag == "Inventory Item")
{
//Here be the issue
inventory.PickUpItem(hitinfo.collider.gameObject.name);
Debug.Log("Hit! " + hitinfo.collider.gameObject.name);
}
}
}
Never mind the raycasts, the Debug.log shows that they work. The only issue is when I call the PickUpItem() function, or try to access variables from the Inventory script, for that matter (I tried Debug.log on an inventory variable, same issue). That is where the null reference exception happens.
Here is the function I'm trying to call:
public void PickUpItem(string newItemName)
{
inventoryItems[invNumberOfItems] = GameObject.Find(newItemName).GetComponent<InventoryItem>();
invNumberOfItems++;
}
The InventoryItem component is just a class attached to each specific item with variables of data like a name an description. I can't test to see if that function even works because the code doesn't get that far.
The Inventory script is attached to a GUIText object (Later to be upgraded to a GUITexture) and all the tags n stuff are correct. I'm stumped... I... I just can't find where I went wrong.
Help pls. =(
Reading this, I got the feeling you're not sure what null reference exceptions are.
In case you do, however, the only possible places (in the shown code) that can cause this are the lines 5 % 6 in your first snippet. One of them evaluates to null.
Well, guide me here. When I test like this (tell me if I'm doing it wrong):
InventoryGUI = GameObject.FindGameObjectWithTag("Inventory GUI");
if (InventoryGUI == null) {
Debug.Log("GUI is null");
}
else {
Debug.Log("GUI is working");
}
inventory = InventoryGUI.GetComponent<Inventory>();
if (inventory == null) {
Debug.Log("Inventory is null");
}
else {
Debug.Log("Inventory is working");
}
Nothing is print to the console. Nothing at all.
it's likely caused by the space in the tag name. afaik, there's nothing in the documentation stating that spaces cannot be used, but believe that it causes issues.
EDIT: and as syclamoth states below, there's a much more efficient way of doing it.
EDIT2: in this recent snippet - if neither of the Debug.Log messages are being displayed in the console, there's a high probability that the script is not even running...
I stand by my original statement: don't use GameObject.Find! It's only causing you trouble here, that you could easily bypass by locating the object in a more reliable way.
I just checked the documentation; the method to finding one gameobject with a tag is FindWithTag. Apparently FindGameObjectWithTag was too easily confused with FindGameObjectsWithTag and they changed it, because I'm pretty sure I've used the singular version of that...
Answer by syclamoth · Sep 04, 2013 at 09:41 AM
For starters, avoid using 'GameObject.Find' and other such string-literal dependant functions. There is almost always a cleaner way. The way you are passing objects between the raycast detection step and the inventory adding step is especially suspect. Consider: what looks more error prone?
inventory.PickUpItem(hitinfo.collider.gameObject.name);
// later
public void PickUpItem(string newItemName)
{
//inside:
GameObject.Find(newItemName)
}
OR:
inventory.PickUpItem(hitinfo.collider.gameObject);
// later
public void PickUpItem(GameObject newItem)
{
//inside:
// Now just add 'newItem'
}
By taking the object's name, and sending that, instead of just sending a direct reference to the object itself, you are introducing potential errors that will make your life generally more difficult.
Finally, make sure that 'inventoryItems' has actually been assigned! From the sounds of things, it should be an array with a reasonably large size- which is a waste of space at best, and yet more potential errors at worst, so maybe consider using a List instead.
$$anonymous$$y apologies, I should have mentioned that I tried gameObject first and I thought that might be causing the null reference for some reason. If I may be so bold, everything inside PickUpItem isn't of much consequence right now because I can't even call the damn thing.
Also, the InventoryItems array, as per my game design, will never rise above 4.
Well, when in doubt, simplify, don't complicate. In this case it's still a pretty good example of how that kind of thing can slow down troubleshooting! That first code snippet, could be simplified just by reducing it to two lines:
[SerializeField]
Inventory inventory;
and then assigning it in the inspector, thus removing another weak link.
That worked =) Thank you, syclamoth! SerializeField is one thing I haven't really used yet. I'll be sure to do more reading on it.
Thanks again! I only wish I had enough rep to upvote you!