- Home /
Trouble with Null Reference in Script
Hello everyone, I'm having a hard time tracking down a null reference error that is occuring between 2 scripts. Just so you know, sometimes the script will fail early (on the 2nd time it activates) or will fail late (after 10+ activations).
For your reference, here is the full error: NullReferenceException: Object reference not set to an instance of an object PushPlatform.Push () (at Assets/Scripts/Rooms/Room 12/PushPlatform.cs:20) PushPlatformManager+c__Iterator3.MoveNext () (at Assets/Scripts/Rooms/Room 12/PushPlatformManager.cs:52)
Here is the 1st script that the error references, the error occurs at: "if (hit.rigidbody.tag == "TDPlatform")"
using UnityEngine;
using System.Collections;
public class PushPlatform : MonoBehaviour {
public float pushPower; //100?,
void FixedUpdate ()
{
//Push();
}
public void Push ()
{
//if (Input.GetKey (KeyCode.P))
//{
//Debug.Log ("P");
RaycastHit hit;
Physics.Raycast(transform.position, -transform.up, out hit, 10f);
Debug.DrawRay(transform.position,-transform.up, Color.red);
if (hit.rigidbody.tag == "TDPlatform")
{
hit.rigidbody.AddForceAtPosition (-transform.up * pushPower, hit.point, ForceMode.Impulse);
Debug.Log ("Pusher hit " + hit.rigidbody.name);
}
else
{
Debug.Log ("the pusher hit something besides the platform");
}
//}
}
}
And here is the 2nd script it references, the error will change but it occurs on one of the case lines ( pushPlatformArray [0,1,2].Push();).
using UnityEngine;
using System.Collections;
public class PushPlatformManager : MonoBehaviour {
// this script goes on TDPlatform1stPlayerLayer,
public float waitBetweenFire; //xx,
public int randomNumber;
public PushPlatform[] pushPlatformArray;
public bool selectionInProgress;
void Awake ()
{
selectionInProgress = false;
pushPlatformArray = new PushPlatform[4];
pushPlatformArray = gameObject.GetComponentsInChildren <PushPlatform>();
}
void FixedUpdate ()
{
Fire();
}
void Fire()
{
if (selectionInProgress == false)
{
StartCoroutine (TriggerPusher(waitBetweenFire));
}
}
IEnumerator TriggerPusher (float time)
{
selectionInProgress = true;
Debug.Log ("selectionInProgress is " + selectionInProgress);
yield return new WaitForSeconds (time);
randomNumber = Random.Range (0,3);
switch (randomNumber)
{
case 0:
pushPlatformArray [0].Push();
Debug.Log ("pushPlatformArray [0] should have pushed");
break;
case 1:
pushPlatformArray [1].Push();
Debug.Log ("pushPlatformArray [1] should have pushed");
break;
case 2:
pushPlatformArray [2].Push();
Debug.Log ("pushPlatformArray [2] should have pushed");
break;
case 3:
pushPlatformArray [3].Push();
Debug.Log ("pushPlatformArray [3] should have pushed");
break;
default:
Debug.Log ("ranndom number failed to trigger a push");
break;
}
selectionInProgress = false;
Debug.Log ("selectionInProgress is " + selectionInProgress);
}
}
Answer by Linus · Feb 09, 2014 at 03:30 PM
hit.rigidbody.tag
should be
hit.transform.tag
$$anonymous$$aking this change seems to have fixed the problem, thank you very much. On a side note, since my script was wrong, why did it even work to begin with?
Unity did not get the problem before it tried to access hit.rigidbody.tag
Right, but then why would it work 2-10ish times before it failed - is what I'm really getting at.
Best guess would be that the raycasts did not hit anything the other times for whatever reason and that part of the code was not ran. hit would be null and just skipped to else not bothering to check if tag is part of rigidbody
Answer by Murkas · Feb 09, 2014 at 03:29 PM
The problem is, that the raycast is not hitting anything or at least nothing with a rigidbody. The raycast function is of type boolean, so you can check, if it hits anything. If it hit anything, you should check, if the hit object has a rigidbody, you can simply check this with if(hit.rigidbody)
. Try the following:
if(Physics.Raycast(transform.position, -transform.up, out hit, 10f)){
if(hit.rigidbody){
if (hit.rigidbody.tag == "TDPlatform")
{
hit.rigidbody.AddForceAtPosition (-transform.up * pushPower, hit.point, ForceMode.Impulse);
Debug.Log ("Pusher hit " + hit.rigidbody.name);
}
else
{
Debug.Log ("the pusher hit something besides the platform");
}
}else{
//Here the hit object does not have a rigidbody
}
}else{
//Here the raycast did not hit anything
}
Although this was not the direct answer to my problem, I do appreciate it as it seems to just be good practice for the future (and will save me some future headaches), thank you.
It is good practice to check if the hitted object has the component you want to access.
I tend to do what you do though if I am only after checking for certain objects. Check if it is the object I want, and let unity crash horribly to let me know if I have miss placed a tag or forgotten to add the correct component.