- Home /
The question is answered, right answer was accepted
NullReferenceException: Object reference not set to an instance of an object
Hi, I am pretty new to C# and unity at the start, plus I am doing this out of my interest, so my question could be basic. However it has bugged me for so long, that I couldn't get it over even after I research it over the internet.
Anyway, here is my question, I have got this error NullReferenceException: Object reference not set to an instance of an object two times over my script.
The first time is when I wanted to set the respawn action only execute after the player enters the "Dying state", I have use Debug.Log to ensure it successfully enters the Dying state, but when I click the respawn button after the player dies, the error pops up.
The second error happens whenever I press the attack button, which I intend to let my player throw grenade or whatever.
Codes as bellow
My PlayerController script, and it works fine
using UnityEngine; using System.Collections;
[RequireComponent(typeof(PlayerPhysics))] public class PlayerController : Entity {
// Player Handling
public float gravity = 20;
public float speed = 8;
public float acceleration = 30;
public float jumpHeight = 16;
public float slideDeceleration = 1;
// System
private float animationSpeed;
private float currentSpeed;
private float targetSpeed;
private Vector2 amountToMove;
// States
[HideInInspector]
public bool Dying;
private bool jumping;
private bool sliding;
private bool still;
private bool falling;
private bool throwing;
private bool droping;
private bool bumping;
// Componenets
private PlayerPhysics playerPhysics;
private Animator animator;
private GameManager manager;
private PlayerAttack attack;
void Start () {
playerPhysics = GetComponent<PlayerPhysics>();
animator = GetComponent<Animator>();
manager = Camera.main.GetComponent<GameManager>();
}
void Update () {
if(GetComponent<Entity>().Died!=true){
Dying=false;
#region player alive movement
// Reset acceleration upon collision
if (playerPhysics.movementStopped) {
targetSpeed = 0;
currentSpeed = 0;
}
// If player is touching the ground
if (playerPhysics.grounded) {
amountToMove.y = 0;
// Jump logic
if (jumping) {
jumping = false;
animator.SetBool("Jumping",false);
}
// Jump
if(!sliding){
if (Input.GetButtonDown("Jump")) {
amountToMove.y = jumpHeight;
jumping = true;
animator.SetBool("Jumping",true);
}
}
// Slide Input & logic
if (Input.GetButton("Slide")) {
sliding = true;
animator.SetBool("Sliding",true);
targetSpeed = 0;
playerPhysics.SetCollider(new Vector3(5,2.2f,1.79f), new Vector3(-0.17f,1.1f,-1.24f));
}
else {
sliding = false;
animator.SetBool("Sliding",false);
playerPhysics.ResetCollider();
}
if(amountToMove.x==0){
still=true;
animator.SetBool("Still", true);
} else {
still=false;
animator.SetBool("Still", false);
}
}
//falling logic
if(!playerPhysics.grounded){
if(!jumping){
falling=true;
animator.SetBool("Falling", true);
}
}
else {
falling=false;
animator.SetBool("Falling", false);
}
// Set animator parameters
animationSpeed = IncrementTowards(animationSpeed,Mathf.Abs(targetSpeed),acceleration);
animator.SetFloat("Speed",animationSpeed);
// Input
if (!sliding) {
//movement
targetSpeed = Input.GetAxisRaw("Horizontal") * speed;
currentSpeed = IncrementTowards(currentSpeed, targetSpeed,acceleration);
// Face Direction
float moveDir = Input.GetAxisRaw("Horizontal");
if (moveDir !=0) {
transform.eulerAngles = (moveDir>0)?Vector3.zero:Vector3.up * 180;
}
}
else {
currentSpeed = IncrementTowards(currentSpeed, targetSpeed,slideDeceleration);
}
// Set amount to move
amountToMove.x = currentSpeed;
amountToMove.y -= gravity * Time.deltaTime;
playerPhysics.Move(amountToMove * Time.deltaTime);
#endregion
}else{
#region player dead movement
Dying=true;
animator.SetBool("Die", true);
targetSpeed=0;
currentSpeed = IncrementTowards(currentSpeed, targetSpeed,slideDeceleration);
amountToMove.x = currentSpeed;
amountToMove.y -= gravity * Time.deltaTime;
playerPhysics.Move(amountToMove * Time.deltaTime);
#endregion
}
//Attack
if (Input.GetButtonDown("LRangeAttack")) {
//attack.Throw();
Debug.Log("throwing now");
GetComponent<PlayerAttack>().Throw();
// throwing = true;
// animator.SetBool("Throwing",true);
}
//complete level (need to set up)
// if(GetComponent<Enemies>().EnemiesNum==0){
// manager.EndLevel();
// }
}
//probably not necessary, may change to second player
void OnTriggerEnter(Collider c) {
if (c.tag == "Checkpoint") {
manager.SetCheckpoint(c.transform.position);
}
//if (c.tag == "Finish") {
// manager.EndLevel();
//}
}
// Increase n towards target by speed
private float IncrementTowards(float n, float target, float a) {
if (n == target) {
return n;
}
else {
float dir = Mathf.Sign(target - n); // must n be increased or decreased to get closer to target
n += a * Time.deltaTime * dir;
return (dir == Mathf.Sign(target-n))? n: target; // if n has now passed target then return target, otherwise return n
}
}
}
then here is my GameManager script, where the first error pops in when I want to respawn
NullReferenceException: Object reference not set to an instance of an object GameManager.Update () (at Assets/Scripts/GameManager.cs:30)
which is line if(GetComponent().Dying=true) in GameManager script
using UnityEngine;
using System.Collections;
public class GameManager : MonoBehaviour {
public GameObject player;
private GameObject currentPlayer;
private GameCamera cam;
private Vector3 checkpoint;
public static int levelCount = 100;
public static int currentLevel = 1;
void Start () {
cam = GetComponent<GameCamera>();
if (GameObject.FindGameObjectWithTag("Spawn")) {
checkpoint = GameObject.FindGameObjectWithTag("Spawn").transform.position;
}
SpawnPlayer(checkpoint);
}
// Spawn player
private void SpawnPlayer(Vector3 spawnPos) {
currentPlayer = Instantiate(player,spawnPos,Quaternion.identity) as GameObject;
cam.SetTarget(currentPlayer.transform);
}
private void Update() {
if (Input.GetButtonDown("Respawn")) {
if(GetComponent<PlayerController>().Dying=true)
Destroy(currentPlayer.gameObject);
SpawnPlayer(checkpoint);
}
}
public void SetCheckpoint(Vector3 cp) {
checkpoint = cp;
}
public void EndLevel() {
if (currentLevel < levelCount) {
currentLevel++;
Application.LoadLevel("Level " + currentLevel);
}
else {
Debug.Log("Beta ends here, more coming~");
}
}
}
and now the second errors in my PlayerAttack script, I have yet completed the function but the error still shows
NullReferenceException: Object reference not set to an instance of an object PlayerController.Update () (at Assets/Scripts/PlayerController.cs:158)
which is line GetComponent().Throw(); in PlayerController script
using UnityEngine;
using System.Collections;
public class PlayerAttack : MonoBehaviour {
public void Throw() {
Debug.Log("THROW");
}
}
It is hard to sort out the reason without knowing more of how your game is structured and seeing a bit more code. In both instances, you are getting the error because your GetComponent() call is failing and returning null. The usual reason for this failure is that the GetComponent(), used this way, need to have the scrip you are attempting to reference on the same game object as the script that is making the GetComponent() call.
ok~ I have put up the whole version of the three scripts now, would that be helpful? Also, regarding your suggestion, I have introduce others function using GetComponent in the same format, just wondering why would they work and these two don't?
Thanks for the explanation, so to my understanding is it because I need to assign a Object for every GetComponent so only in that way unity is able to distinguish which function is direct to which object?
Well, GetComponent is a method of a GameObject, so you have to call it for a certain GameObject like this:
Object.GetComponent<Type>()...
If you omit the "Object." then the method will be always called for the current object. That might be fine in some cases, but if the component you are looking for is assigned to a different object, it can't be found this way.
Great thanks to you guys, I have fixed the error~~ p.s. Do you want to convert the comments to answer or should i just close this question?
Answer by Gnometech · Feb 20, 2014 at 03:51 PM
Robert is completely right. You have to call Getcomponent on the GameObject that actually has the component. If these scripts are assigned to different gameobjects, the call will return null resulting in the error.
One way to resolve this is to add references to the other gameobjects in your script.
Example: To resolve the first issue, add
public GameObject playerObject;
to the GameManager. In the inspector you can drag & drop your player gameobject into this one to set it.
Then in line 30, you write
if(playerObject.GetComponent<PlayerController>().Dying==true)
(Note that for comparisons you HAVE TO use == and not = as the latter is reserved for assigning. In this case you can even omit the == true entirely as Dying is already a bool).
I converted @Gnometech's comment to an answer since it was the complete explaination of the problem.
This Exception will also occur if you are trying to access a member function of uninitialized object. For Private GameObject myObject; trying to access name of an uninitialized GameObject. Check this out -- object reference not set to an instance of an object unity
Answer by CharlieLama · Jun 08, 2016 at 03:57 PM
A thing you can also do is : hit.collider.gameObject.GetComponent().Dying == true;
this is a better solution if you have more then one player you would like to check. then the script also doesnt have to be on the same object but then you need to have a raycast to look what you hit, (Raycasthit hit, its the point where the raycast hits an object and then checks whether that object has the script, PlayerController)
Just something that might come in handy later, or for other people :)
Follow this Question
Related Questions
NullReferenceException with an Array 2 Answers
Phantom / ghost reference throwing null reference error 0 Answers
NullReferenceException help 1 Answer