I keep getting errors when I delete a gameobject from my list

Here’s my code:

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class RadarScript : MonoBehaviour
{
    public List<GameObject> TrashItems;
    public GameObject Collectibles;
    public float Distance;
    public float NearestDistance = 100000;
    public TextMeshPro TextObject;
    public GameObject NearestObject;
    // Start is called before the first frame update
    void Start()
    {
       
    }

    // Update is called once per frame
    void Update()
    {
        TrashItems = new List<GameObject> (GameObject.FindGameObjectsWithTag("Trash"));
       
       
    }
    void LateUpdate() {
        for (int i = 0; i < TrashItems.Count; i++)
        {
            if (TrashItems[i] != null) {
                Distance = Vector3.Distance(transform.position, TrashItems[i].transform.position);
            if (Distance < NearestDistance) {
                NearestDistance = Distance;
                NearestObject = TrashItems[i];
            }
            TextObject.text = "Distance: " + Vector3.Distance(transform.position, NearestObject.transform.position);
            }

        }
       
    }
       
   
   
}

It all works perfectly fine, but I have another script that deletes one of the trash items whenever they are collected. When the item gets deleted, I get this error:


I assume it is because the for loop is trying to access a destroyed gameobject, but I have no clue how to fix it. I have tried removing the object from the list when I destroy it, and I have tried setting up the if statement to make sure the object is still there.

I’m newish to unity so I can believe there’s something simple I’m missing. Any help is much appreciated.

The message includes a callstack so you know which line the error gets thrown. It’s also important to know how to attach the debugger, stop execution, step through the code to learn what it is doing.

The problem is likely due to the list being obtained in update, the other script destroying one of these objects, and then LateUpdate runs with one or more of these objects destroyed.

Generally:

  • calling GameObject.Find* every Update is terribly inefficient
  • having all fields public is not advisable (use [SerializeField] private …)
  • then when another script used to modify a public field, instead it has to call a method on the target component to perform this work - encapsulation is essential, otherwise this RadarScript will have no way of knowing which of these trash items had been destroyed by some other component or whether it should simply update its trashed items list

The better solution would be to have a component that is the only place that handles trash items, let’s call it TrashBin. This will essentially just be a collection of trash items, initially empty. As some component “creates trash” it will “add” the new trash item to the TrashBin so that the list grows. If a trash item ought to be destroyed any component can call DestroyTrash on TrashBin so it can both Destroy and remove the object from the list.

1 Like

Yes, the answer is always the same… ALWAYS!

How to fix a NullReferenceException error

https://forum.unity.com/threads/how-to-fix-a-nullreferenceexception-error.1230297/

Three steps to success:

  • Identify what is null ← any other action taken before this step is WASTED TIME
  • Identify why it is null
  • Fix that