# error for trying to reference an object that has been destroyed

## Recommended Posts

I'm getting an error that I can't seem to track down. I understand what the error is telling me, just not why I'm getting it. Here is the exact error:

MissingReferenceException: The object of type 'AssaultRiflePickUp' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine) (at C:/buildslave/unity/build/artifacts/generated/common/runtime/MonoBehaviourBindings.gen.cs:62)
AssaultRiflePickUp.StartCoroutine (Single delay) (at Assets/Scripts/AssaultRiflePickUp.cs:77)
AssaultRiflePickUp.AssaultRifleShot (UnityEngine.GameObject mainBall) (at Assets/Scripts/AssaultRiflePickUp.cs:89)
Ball.OnCollisionEnter2D (UnityEngine.Collision2D collider) (at Assets/Scripts/Ball.cs:63)

To give some more info, I have an arkanoid style clone, and I have a special pick up called AssaultRiflePickUp. I collect the pick up, and then the next time the ball hit's my paddle, it should iterate through the code to do what the pick up does. The problem is that I get this error instead once the ball hit's the paddle. The AssaultRifleShot method is called from an event on the Ball class. The event is called when the Ball hits the paddle and the pick up is active. I have not used events before but I believe I have it set up correctly. When the pick up first gets hit by the ball, the gameObject is destroyed, but a clone of the AssaultRiflePickUp class is instanced on a list to be accessed. For whatever reason, I'm not getting this instance but seem to be getting the instance that has been destroyed. I'm not sure why though. Maybe someone can spot where I'm messing up.

Ball class event:

	public delegate void BallHitPaddle(GameObject ball);

and then in the OnCollisionEnter2D method....

if (collider.gameObject.name == "Paddle" && this.mainBall)
{
{
}
}

Here is what happens when the pick up collides with the ball or paddle:

public void OnCollisionEnter2D (Collision2D collision)
{	//tweak is used to make sure the pick up does not get stuck moving in a vertical loop
Vector2 tweak = new Vector2 (UnityEngine.Random.Range(0f, 0.2f),UnityEngine.Random.Range(0f, 0.2f));

this.gameObject.GetComponent<Rigidbody2D>().velocity += tweak;

//if the pickup makes contact with the paddle or ball....
if (collision.gameObject.tag == "Paddle" || collision.gameObject.tag == "Ball")
{
Destroy(gameObject); //...and finally destroy pick up object
}
}

And here is the AssaultRiflePickUp:

public class AssaultRiflePickUp : BasePickUp
{
private int AmmoRemaining = 35;
private float timer = 0.3f;

public GameObject newBall;

void Start ()
{

//find the ball and assign it to this variable
foreach (Ball ball in GameManager.pickUpManager.allBalls)
{
if (ball.mainBall)
{
mainBall = ball;
}
}
//subscribe to events
mainBall.onBallCollided += DestroyExtraBalls;
Debug.Log("Start");
}

public override void ActivatePickUp (MonoBehaviour coroutineHost)
{

}

public void SpecialShot ()
{
Debug.Log("SpecialShot");
Vector3 mainBallVector = mainBall.GetComponent<Rigidbody2D>().velocity; //grab mainBall's direction and speed before making it a destroyable ball
mainBall.GetComponent<Ball>().mainBall = false;

Instantiate(newBall);
newBall.transform.position = paddle.transform.position + ballSpawnOffset; //use the original ball's vector3 to follow it directly
newBall.GetComponent<Rigidbody2D>().velocity = mainBallVector;
}

public void DestroyExtraBalls (GameObject ball)
{
if (GameManager.pickUpManager.allBalls.Count > 1)
{
}

//TODO: Implement observer pattern to watch for balls colliding with something. If they do and they are not the main ball, destroy them.
}

public void DestroyPickUp ()
{
Debug.Log("DestroyPickUp");
Destroy (GameManager.pickUpManager.pickUpQueue [0]);
GameManager.pickUpManager.pickUpQueue.RemoveAt (0);
GameManager.pickUpManager.pickUpActive = false;
}

//a timer used for timed pick ups
public IEnumerator PowerUpTimer (float delay)
{
Debug.Log("PowerUpTimer");
yield return new WaitForSeconds (delay);
SpecialShot();
}

//The coroutine is used to start a short timer so that the balls don't spwn on top of each other all at the same time.
public void StartCoroutine (float delay)
{
StartCoroutine(PowerUpTimer(delay));
}

//Controls the pick up's cycle
public void AssaultRifleShot (GameObject mainBall)
{
if (AmmoRemaining > 0)
{
//if there is ammo remaining, set the main ball to just a normal ball so it can be destroyed on impact and then start coroutine
mainBall.GetComponent<Ball> ().mainBall = false;
mainBall.GetComponent<Ball> ().onBallHitPaddle -= AssaultRifleShot; //unsubscribe to event when mainBall is set to false.
StartCoroutine(timer);

AmmoRemaining -= 1;
}
else
{
DestroyPickUp();
}
}
}

##### Share on other sites

I've narrowed the code down to this section here on the Ball class:

if (collider.gameObject.name == "Paddle" && this.mainBall)
{
{
}
}

This is in the OnCollisionEnter2D method and is the notifier for the event. The AssaultRifleShot method in the AssaultRiflePickUp class is the listener. I'm confused why I'm getting a null reference though since I'm doing a null check. I believe what is happening is the pickup game object is being destroyed without unsubscribing. This game object's script gets cloned into a pick up queue list before it is destroyed, and then it is destroyed. i tried using OnDestroy() to unsubscribe it, but if I do that, then the event never gets hit, so I'm guessing the clone isn't subscribed? The OnDestroy() does however get rid of the error. Does the Start() function get called when you clone a script? i think that is really what this boils down to is the clone script is not subscribed to the event.

## Create an account

Register a new account

1. 1
2. 2
Rutin
24
3. 3
4. 4
JoeJ
18
5. 5

• 14
• 23
• 11
• 11
• 9
• ### Forum Statistics

• Total Topics
631766
• Total Posts
3002234
×

## Important Information

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!