I’m making a platform jumper game (similar to Doodle Jump, if you’ve played that) and I want to destroy the platforms below 10 units of my player.
I have a “Delete” script to do this, but I get an error: “The object of type ‘GameObject’ has been destroyed but you are still trying to access it.”
Here’s my script:
using UnityEngine;
using System.Collections;
public class Delete : MonoBehaviour {
GameObject[] platform;
// Use this for initialization
void Start () {
platform = GameObject.FindGameObjectsWithTag("Platform");
}
// Update is called once per frame
void Update () {
foreach(GameObject p in platform)
{
if (p.transform.position.y < (SpawnPlatform.playerTrans.position.y - 10))
{
Destroy(p);
}
}
}
}
AS it says here, it’s dangerous to change the content of a collection with a foreach. In your case, I think the destruction don’t allow the loop to iterate to the next. You might a more skilled c# programmer to confirm that though.
You should use a trigger and Destroy inside OnTriggerEnter, so you won’t even need a loop.
You’re destroying all platforms 10 units below the player, even those that aren’t under the player - is this what you wanna do?
Anyway, your problem has another cause: you should check if the platform exists (not null) before doing anything with it, like this:
...
void Update () {
foreach(GameObject p in platform)
{
if (p) // if the platform still exists...
{
if (p.transform.position.y < (SpawnPlatform.playerTrans.position.y - 10))
{
Destroy(p);
}
}
}
}
...
When an object is destroyed, all references to it become null - including the platform array elements. Since you’re destroying platforms every Update, the second update cycle encounters several null references in the platform array, causing the errors.
I tried adding the OnTriggerEnter, but it gave me the same issue.
Destroy cannot set all references to null. It’s impossible because there is no way in C# to track all references to all objects. Even such a way exist it would take too much processing time. Yes, GC does this but it’s an underlying system under C# itself. Please note than destroying in term of unity just removes the object from the system but it cannot watch all your references.
You also can call Destroy in foreach when iterating simple arrays. That’s not dangerous because there is no iterator or list or something else. You just get reference to the next element in array on each iteration. And this is the problem in your case. Because if any of platforms is destroyed you keep to get reference to “destroyed” platform on subsequent updates.
The solution is to remove the object from array that drops the reference to it.
for (int i = 0, n = platforms.Length; i < n; i++)
{
GameObject p = platforms*;*
*if (p)*
*{*
*if (p.transform.position.y < (SpawnPlatform.playerTrans.position.y - 10))*
*{*
*Destroy(p);*
_platforms *= null;*_
_*}*_
_*}*_
_*}*_
_*```*_