Null Reference Error C#

Hi guys,

I’m following the 3D buzz tutorials and attempting to allow my character to pickup an object. This object is a crystal and becomes attached to the players “hand” joint to make it look as if theyre carrying. However, at the moment i’m prototyping it with a simple cube exported from a 3D package as named “crystal object” and recieving this error:

NullReferenceException
PickUp.Awake () (at Assets/_Scripts/Enviro Puzzle Scripts/PickUp.cs:22)

or

NullReferenceException: Object reference not set to an instance of an object
PickUp.Reset () (at Assets/_Scripts/Enviro Puzzle Scripts/PickUp.cs:66)
UnityEditorInternal.InternalEditorUtility:HierarchyWindowDrag(HierarchyProperty, Boolean)
UnityEditor.DockArea:OnGUI()
My code is below!

void Awake()
	{
		itemAnim = transform.Find("CrystalObject").animation; // name of the object
		sphereCollider = GetComponent("SphereCollider") as SphereCollider;
		initialPosition = transform.position;
		initialRotation = transform.rotation;
	}

cheers!!

That’s actually not enough code to really pinpoint the problem, but I think that you are trying to assign the animation component, yet the “CrystalObject” was not found in the object’s hierarchy (line 3 of the script above).

Try to do the following to confirm that:

void Awake()
	{
		Transform item = transform.Find("CrystalObject");
		itemAnim = item.animation; // <-- you may get a NullReference Exception here if item was not found
		
		sphereCollider = GetComponent("SphereCollider") as SphereCollider;
		initialPosition = transform.position;
		initialRotation = transform.rotation;
	}

Note that Transform.Find() only searches on the first level of the hierarchy. If the CrystalObject is nested deeper you would not be able to find it that way. In that case you will either need to provide a path to the Find function, or write a custom find function.

Path: Unity - Scripting API: Transform.Find

Yes i got the error on the line you mentioned, but i have no idea why its nothing complicated its simply an object that has no function other then picking up and putting somewhere and at this moment… a cube.

To be honest, i have no idea why animation is included as the object doesnt actually animate, its just from the tutorials i followed did that…

Once i unpaused the game from the error (“as unity paused the game when a null reference was made”) I then attempted to grab the object by pressing the button within distance and got a further error:

NullReferenceException
UnityEngine.Animation.Stop () (at C:/BuildAgent/work/b0bcff80449a48aa/Runtime/ExportGenerated/Editor/Animations.cs:372)
PickUp.LateUpdate () (at Assets/_Scripts/Enviro Puzzle Scripts/PickUp.cs:51)

I assume its for the same issue, but ive included all my code - if you could help itd be greatly appreciated!

using UnityEngine;
using System.Collections;


// ADJUST THE BONE FOR THE CHARACTER VIA THE RIG AND ITS PUBLIC ACCESS

public class PickUp : MonoBehaviour 
{
	public Vector3 Offset = new Vector3(0, -0.2f, 0);
	public Vector3 ScalingFactorWhenHeld = new Vector3(0.4f, 0.4f, 0.4f);
	
	private Vector3 initialPosition;
	private Quaternion initialRotation;
	private bool inRange = false;
	private bool isHeld = false;
	private Animation itemAnim;
	
	private SphereCollider sphereCollider;
	
	//void Awake()
	//{
		//itemAnim = transform.Find("CrystalObject").animation; // name of the object
	//	sphereCollider = GetComponent("SphereCollider") as SphereCollider;
	//	initialPosition = transform.position;
	//	initialRotation = transform.rotation;
//}
		    void Awake()
        {
            Transform item = transform.Find("CrystalObject");
            itemAnim = item.animation; // <-- you may get a NullReference Exception here if item was not found
           
            sphereCollider = GetComponent("SphereCollider") as SphereCollider;
            initialPosition = transform.position;
            initialRotation = transform.rotation;
        }
	
	void OnTriggerEnter()
	{
		inRange = true;
	}
	
	void OnTriggerExit()
	{
		inRange = false;
	}
	
	void LateUpdate()
	{
	 	if (inRange  !TP_Controller.Instance.IsHolding  Input.GetButton("Player Use"))
		{
			itemAnim.Stop();
			TP_Controller.Instance.IsHolding = true;
			TP_Controller.Instance.ObjectHeld = this;
			isHeld = true;
			TP_Controller.Instance.Use();
		}
		
		if (isHeld)
		{
			sphereCollider.radius = 0;
			transform.localScale = ScalingFactorWhenHeld;
			transform.position = TP_Controller.Instance.TargetHand.position + Offset;
			transform.rotation = Quaternion.Euler(TP_Controller.Instance.TargetHand.rotation.eulerAngles.x,
											      TP_Controller.Instance.TargetHand.rotation.eulerAngles.y + 90,
												  TP_Controller.Instance.TargetHand.rotation.eulerAngles.z);
		}
	}
	
	public void Reset()
	{
		isHeld = false;
		transform.position = initialPosition;
		transform.rotation = initialRotation;
		transform.localScale = new Vector3(1, 1, 1);
		sphereCollider.radius = 1;
		itemAnim.Play();
		
	}
}

It’s all related to the same issue. As I mentioned - the Transform.Find() function expects the object you want to find one level below the current object in the hierarchy. Once that CrystalObject should be attached to your main object, pause the game and check in the scene hierarchy where it is actually located. If it is nested deeper than 1 level, there’s no way you can use Transform.Find without providing the full path down the hierarchy (see the link I added to my first post which shows you how to do that).

edit: Just noticed again that you are actually making that call to Find() directly in Awake() which means that the object is already provided in the hierarchy. Are you sure you nested your objects correctly?

However, all the Find() functions are generally very slow anyways. It’s good for tutorial purposes but apart from that you should not really use that. So a way around that would be to write some kind of helper component and attach that to your CrystalObject. It doesn’t need to do any logic, you can even remove any Start() or Update() function from that, so that you end up with a dummy script:

using UnityEngine;
using System.Collections;

public class DummyClass : MonoBehavior
{

}

Then instead of Find() you can e.g. use the following:

Transform item = transform.GetComponentInChildren<DummyClass>().transform;

GetComponentInChildren() actually travels through all the children and tries to find the component provided.

But just to say that: Using dummy classes just to find objects in the hierarchy is of course not the way to go. In reality you will most likely have classes you use anyway, or use tags, or provide the object directly by assigning it in the Inspector, or or or. Yet I personally have never used Find().

you’re right, it’s not complicated; unity is case sensitive, the cube needs to be called exactly “CrystalObject” not “crystalobject”, “crystal object” or “Crystal Object”.

SOLVED MYSELF AM EXTREMELY PROUD <3

Cheers for the advice guys!

It’s always good to tell people what you actually did. Not only because someone other than yourself spent time on the issue, but also because people actively search this forum and might find your solution helpful. :wink: What did you do?