Sorry for my English… and sorry because my code is in Spanish
I have a problem… I make a List where I add GameObjects, if certain conditions are met, they are destroyed and removed from the List. The problem is when I remove and Destroy the last GO from the List… “The object of type ‘GameObject’ has been destroyed but you’re still trying to access to it”.
I think that the main problem is the “foreach”, it looks every space on the List, and the GameObjects that are removed and destroyed still have a presence on the List… How can i solve this? (problem in line 139)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class principal : MonoBehaviour {
public GameObject cubo;
public int cola = 5;
int CuboNumero = 1;
int nivelCubo = 0;
float subir = -3.5f;
float constanteZ = -2.19f;
float tiempo = 0;
float tiempoMoverCubo;
float AleatorioMenor = 0.15f, AleatorioMayor = 0.3f;
bool volviendo = false;
bool crearCubos = false;
private List<GameObject> lista = new List<GameObject>();
// Use this for initialization
void Start () {
CrearCubos();
}
// Update is called once per frame
void Update () {
tiempo = tiempo + Time.deltaTime;
if (tiempo>=tiempoMoverCubo && crearCubos==false)
MoverCubos();
if (Input.GetKeyDown(KeyCode.Space) && crearCubos == false)
PararCubos();
if (tiempo>=1.5f && crearCubos==true)
CrearCubos();
BorrarCubos();
}
//creara los cubos cuando sea necesario / It will make the cubes when necessary
void CrearCubos(){
for (int i=0;i!=cola;i++)
{
cubo=(GameObject)GameObject.Instantiate(cubo, new Vector3(-4.5f + i,-4.5f + nivelCubo,constanteZ),Quaternion.identity);
cubo.GetComponent<Identidad>().numero = CuboNumero;
cubo.transform.name ="Cubo " + CuboNumero.ToString();
cubo.renderer.material.color=Color.blue;
cubo.GetComponent<Identidad>().activo = true;
cubo.GetComponent<Identidad>().borrar = false;
lista.Add(cubo);
CuboNumero++;
}
crearCubos = false;
tiempoMoverCubo=Random.Range(AleatorioMenor,AleatorioMayor);
tiempo = 0f;
}
//Movera los cubos / it will moves the cubes
void MoverCubos(){
float siguiente = -1f;
foreach (GameObject parte in lista){
if (parte.GetComponent<Identidad>().activo == true)
{
siguiente++;
parte.transform.position = new Vector3(subir + siguiente,-4.5f + nivelCubo,constanteZ);
}
}
if (subir + siguiente==4.5f)
volviendo=true;
else if (subir==-4.5f)
volviendo=false;
if (volviendo==false)
subir+=1f;
else
subir-=1f;
tiempo=0f;
}
//parara los cubos / it will stop the cubes
void PararCubos(){
foreach (GameObject parte in lista){
if (parte.GetComponent<Identidad>().activo == true){
parte.GetComponent<Identidad>().activo = false;
parte.GetComponent<Identidad>().x = parte.transform.position.x + 5.5f;
parte.GetComponent<Identidad>().y = parte.transform.position.y + 5.5f;
if (parte.GetComponent<Identidad>().y!=1)
if (ComprobarCubos(parte))
parte.renderer.material.color = Color.green;
else{
cola--;
parte.renderer.material.color = Color.red;
parte.GetComponent<Identidad>().borrar = true;
}
else
parte.renderer.material.color = Color.green;
}
}
ResetearParametros();
}
//reseteara los parametros que realizan el movimiento de los cubos / it will reset the parameters
void ResetearParametros(){
subir = -3.5f;
volviendo = false;
nivelCubo++;
crearCubos = true;
AleatorioMenor = AleatorioMenor * 0.9f;
AleatorioMayor = AleatorioMayor * 0.95f;
}
//comprobara si debajo de los cubos activos... hay cubos / it will check if there are cubes belows the actives
bool ComprobarCubos(GameObject objeto){
foreach (GameObject parte in lista)
{
if (parte.GetComponent<Identidad>().y + 1 == objeto.GetComponent<Identidad>().y)
if (parte.GetComponent<Identidad>().x == objeto.GetComponent<Identidad>().x)
return true;
}
return false;
}
//borrara los cubos / it will delete the cubes
void BorrarCubos(){
foreach (GameObject parte in lista){
if (parte.GetComponent<Identidad>().borrar == true){
lista.Remove(parte);
Destroy(parte);
}
}
//lista.RemoveAll( delegate(GameObject o) { return o == null;});
}
}
After a GameObject has been destroyed, any references to it will be NULL. Do a For loop instead of a foreach loop and check each slot for NULL, or use a list method like RemoveAll:
for (int i = 0; i < lista.Count; i++)
{
GameObject parte = lista[i];
if (parte.GetComponent<Identidad>().borrar == true)
{
lista.RemoveAt(i);
i--;
Destroy(parte);
}
}
“MissingReferenceException: The object of type ‘GameObject’ has been destroyed but you’re still trying to access it”
still have the same problem… it happens when the last gameObject is removed
Edit: i just have seen the mistake: you are decreasing i but don’t remove the element from the list, so you stay at the same value for i forever (in theory). Therefore you try to destroy the game object in the next iteration again.
So you have to remove it from the list when you call i–;
I tried your code, but it is the same as mine. I have tried many codes, where all destroy it from the list, then remove it, some of them making a "if (lista == null)", Unity always say i’m trying to access to the destroyed object… is like the gameobject, even being null and being out from the list, still have a presence in the project… I forget to remove the i-- from your code… but i have tried this: ```csharp
for (int i = 0; i < lista.Count; i++)
{
GameObject parte = lista[i];
if (parte.GetComponent<Identidad>().borrar == true)
{
Destroy(parte);
}
}
lista.RemoveAll(i => i == null);*
``` and it is still the same… the only difference is now I have this problem: “MissingReferenceException: The object of type ‘GameObject’ has been destroyed but you’re still trying to access it”, when any cube (gameobject) is removed from the game (not only the last).
Same problem… it says the same when the last gameobject on the list is removed and destroyed. I also tried to change all “if’s” in all foreach, so it could check if the gameobject was already null… but still the same problem
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class principal : MonoBehaviour {
public GameObject cubo;
public int cola = 5;
int CuboNumero = 1;
int nivelCubo = 0;
float subir = -3.5f;
float constanteZ = -2.19f;
float tiempo = 0;
float tiempoMoverCubo;
float AleatorioMenor = 0.15f, AleatorioMayor = 0.3f;
bool volviendo = false;
bool crearCubos = false;
private List<GameObject> lista = new List<GameObject>();
// Use this for initialization
void Start () {
CrearCubos();
}
// Update is called once per frame
void Update () {
tiempo = tiempo + Time.deltaTime;
if (tiempo>=tiempoMoverCubo && crearCubos==false)
MoverCubos();
if (Input.GetKeyDown(KeyCode.Space) && crearCubos == false)
PararCubos();
if (tiempo>=1.5f && crearCubos==true)
CrearCubos();
BorrarCubos();
}
//creara los cubos cuando sea necesario / It will make the cubes when necessary
void CrearCubos(){
for (int i=0;i!=cola;i++)
{
cubo=(GameObject)GameObject.Instantiate(cubo, new Vector3(-4.5f + i,-4.5f + nivelCubo,constanteZ),Quaternion.identity);
cubo.GetComponent<Identidad>().numero = CuboNumero;
cubo.transform.name ="Cubo " + CuboNumero.ToString();
cubo.renderer.material.color=Color.blue;
cubo.GetComponent<Identidad>().activo = true;
cubo.GetComponent<Identidad>().borrar = false;
lista.Add(cubo);
CuboNumero++;
}
crearCubos = false;
tiempoMoverCubo=Random.Range(AleatorioMenor,AleatorioMayor);
tiempo = 0f;
}
//Movera los cubos / it will moves the cubes
void MoverCubos(){
float siguiente = -1f;
foreach (GameObject parte in lista){
if (parte.GetComponent<Identidad>().activo == true)
{
siguiente++;
parte.transform.position = new Vector3(subir + siguiente,-4.5f + nivelCubo,constanteZ);
}
}
if (subir + siguiente==4.5f)
volviendo=true;
else if (subir==-4.5f)
volviendo=false;
if (volviendo==false)
subir+=1f;
else
subir-=1f;
tiempo=0f;
}
//parara los cubos / it will stop the cubes
void PararCubos(){
foreach (GameObject parte in lista){
if (parte.GetComponent<Identidad>().activo == true){
parte.GetComponent<Identidad>().activo = false;
parte.GetComponent<Identidad>().x = parte.transform.position.x + 5.5f;
parte.GetComponent<Identidad>().y = parte.transform.position.y + 5.5f;
if (parte.GetComponent<Identidad>().y!=1)
if (ComprobarCubos(parte))
parte.renderer.material.color = Color.green;
else{
cola--;
parte.renderer.material.color = Color.red;
parte.GetComponent<Identidad>().borrar = true;
}
else
parte.renderer.material.color = Color.green;
}
}
ResetearParametros();
}
//reseteara los parametros que realizan el movimiento de los cubos / it will reset the parameters
void ResetearParametros(){
subir = -3.5f;
volviendo = false;
nivelCubo++;
crearCubos = true;
AleatorioMenor = AleatorioMenor * 0.9f;
AleatorioMayor = AleatorioMayor * 0.95f;
}
//comprobara si debajo de los cubos activos... hay cubos / it will check if there are cubes belows the actives
bool ComprobarCubos(GameObject objeto){
foreach (GameObject parte in lista)
{
if (parte.GetComponent<Identidad>().y + 1 == objeto.GetComponent<Identidad>().y)
if (parte.GetComponent<Identidad>().x == objeto.GetComponent<Identidad>().x)
return true;
}
return false;
}
//borrara los cubos / it will delete the cubes
void BorrarCubos(){
for (int i = 0; i < lista.Count; i++)
{
GameObject parte = lista[i];
if (parte.GetComponent<Identidad>().borrar == true)
{
lista.RemoveAt(i);
i--;
Destroy(parte);
}
}
/*List<GameObject> tempList = lista.Where(i => i != null && i.GetComponent<Identidad>().borrar).ToList();
foreach(GameObject GO in tempList)
{
Destroy(GO);
}
lista.RemoveAll(i => i == null);*/
//lista.RemoveAll( delegate(GameObject o) { return o == null;});
}
}
and this is the error:
MissingReferenceException: The object of type ‘GameObject’ 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.Object.Internal_InstantiateSingle (UnityEngine.Object data, Vector3 pos, Quaternion rot) (at C:/BuildAgent/work/d63dfc6385190b60/artifacts/EditorGenerated/UnityEngineObject.cs:74)
UnityEngine.Object.Instantiate (UnityEngine.Object original, Vector3 position, Quaternion rotation) (at C:/BuildAgent/work/d63dfc6385190b60/artifacts/EditorGenerated/UnityEngineObject.cs:84)
principal.CrearCubos () (at Assets/scripts/principal.cs:56)
principal.Update () (at Assets/scripts/principal.cs:41)
and again… the function where i remove the game object is at ln 138, and where i call it is in lv 43
Oh really… i was closed in the same function during a week… and the error was in another function… :O, thanks for the help… i need to see more the exception. It was weird, becuz the project worked fine, until i made the remove function (or BorrarCubos())
My last response uses extension methods that are likely made available in System.Linq, though they could be from System, System.Collections, or System.Collections.Generic.