Cant find a good explanation of a null reference..

Can someone help me understand what is happening when I get a null reference error, or is that too generic of a question to answer? To be more specific, its this error and I get it all the time and I dont understand what it means:

NullReferenceException: Object reference not set to an instance of an object

Can someone break this down like they are talking to a child and help me understand what is happening here?

Also, for bonus extra credit, here is the situation I am having where I am receiving this error:

When the “Fire weapon” button is pressed, I instantiate an arrow from my position.

void Update () 
	{
		if(Input.GetButtonDown("Fire Weapon"))
		{
			//Position to launch the arrow from:
			launchPosition = cameraHeadTransform.TransformPoint(0,0, 0.0f);
			
			
			//create the arrow
			Instantiate(arrow, launchPosition, Quaternion.Euler(cameraHeadTransform.eulerAngles.x, 
						myTransform.eulerAngles.y, 0));	

Next, inside of my if statement there is another if statement that basically says, if I continue to hold down the “Fire Weapon” button, then increasingArrowPower becomes true which is then used in a Do While loop which adds +25 to the transferArrowSpeed variable. The idea is that as long as I hold down “fire weapon” I am adding +25 to transferArrowSpeed up to a max of 200(maxArrowPower).

if(Input.GetButton("Fire Weapon"))
			{
				increasingArrowPower = true;
			}
			
		}
			
		do
		{
			transferArrowSpeed += 25;
		}
		while(increasingArrowPower = true && transferArrowSpeed <= maxArrowPower);
	}

THEN, if I havent put you to sleep yet, I use GetComponent to access transferArrowSpeed and use it on my arrow script (which is on the arrow) and set the amount of force to apply to the arrow.

	//Get arrow speed from ShootArrow...
	ShootArrow otherScript;
		otherScript = GetComponent<ShootArrow>();
		otherScript.transferArrowSpeed = arrowSpeed;

Then…

void FixedUpdate () {
	//send the arrow forward
	rigidbody.AddRelativeForce(Vector3.forward * arrowSpeed);

So apparently somewhere along the way I am getting this null reference error which by the way is on the line: otherScript.transferArrowSpeed = arrowSpeed;

You get BIG TIME bonus credit if you figure this one out lol. Thanks!

What this means is that you are trying to reference a gameObject through some data member, but the variable is EMPTY (not set to a specific object)

in this case, the problem is the line:

otherScript = GetComponent<ShootArrow>();

this is intended to INITIALIZE “otherScript” with a reference to the instance of ShootArrow script, which it is looking for on this object…

However, it is not finding it, hence when you attempt to say:

   otherScript.transferArrowSpeed = arrowSpeed;

otherScript is in fact NULL, and not referenced to the desired script…

probably the script you are seeking “ShootArrow” is not attached to the same object

Say ,for example, if I create a data member:

GameObject myObject;

this is a NULL reference (at least so far)

now I say

myObject = GameObject.Find("Some Name");

if this WORKS, myObject is no longer empty, or NULL… Instead it is REFERENCING a specific object. BUT, if the search does NOT turn up an object named “Some Name”, myObject is still null, and that’s what’s happening here

NOW, how to fix? It sounds like the GetComponent line in this case is meant to get the component ShootArrow off of the ARROW object, which we just instantiated, correct? In which case, you can fix this by simply checking the intended object… to reference it, we can create a variable:

void Update () 
    {
     GameObject myArrow;    //add this
     ...etc

then we can use this to store the arrow when we create it:

…etc

     //create the arrow
     myArrow = Instantiate(arrow, launchPosition, Quaternion.Euler(cameraHeadTransform.eulerAngles.x, 
             myTransform.eulerAngles.y, 0)); 

This way, we have a reference to the CORRECT object to use GetComponent on:

   otherScript = myArrow.GetComponent<ShootArrow>();

Hope this helps!

From what I can see, GetComponent() is failing to find that component, and so it’s returning null.

Is the “ShootArrow” script attached to the same object as the script that you posted above, or is it attached to the arrow that you instantiate?

If the answer is the latter, try adding another property to the script:

Arrow myArrow;

Then when creating your instance of the arrow

myArrow = Instantiate(arrow, launchPosition, Quaternion.Euler(cameraHeadTransform.eulerAngles.x, 
             myTransform.eulerAngles.y, 0));

When grabbing the ShootArrow script it would be more like

ShootArrow otherScript = myArrow.GetComponent<ShootArrow>();

A reference variable is a variable that holds the address of another variable. In old C, they were called pointers as they were pointing to another variable and were used like

*ptr = &variable

That still scares a lot of beginners…In C#, they are called reference but the compiler still use ptr to name them at the IL level (the .NET assembly level).

When you use:

otherScript = GetComponent<ShootArrow>();

you declare a variable otherScript that will receive the address of the ShootArrow component that is stored somewhere in the memory. When you use the variable, the compiler finds an address, jumps there and actually finds the component you want to use.

If for some reasons, the component is not found, the function GetComponent returns null meaning the variable does not point anywhere. When trying to use the variable, the compiler returns an error, Null reference variable. This is why it is always useful to use if statement to check if the reference exists or better to use a try and catch so that you can fix the issue or use finally as a last resort. This way your game won’t do what you want but it won’t crash…

If you feel like understanding a little more about how memory works, I would recommend this:

GameObject arrow = (GameObject)Instantiate(arrow, launchPosition, Quaternion.Euler(cameraHeadTransform.eulerAngles.x, myTransform.eulerAngles.y, 0));
if(arrow.rigidbody) 
   arrow.rigidbody.AddRelativeForce(Vector3.forward * arrowSpeed); 
else arrow.AddComponent(Rigidbody);    
   arrow.rigidbody.AddRelativeForce(Vector3.forward * arrowSpeed);