Hi all,
Been struggling with trying to remove nulls from a list before it sorts the list but its not working so I figured id see if anyone here has any ideas.
The concept is that I have a list of nearby objects (enemies, asteroids, etc). The list sorts itself by distance. The problem comes when the player destroys the enemy it goes missing in the list. In the Update() function I added the count backwards to remove nulls from the list and then try to sort. However, the list is not being cleared of the nulls at all and then I get null reference exceptions when the list tries to sort itself. The code for the two functions are below, does anyone see where I might be going wrong?
void Update()
{
//try to remove nulls
if (spaceObjs.Count > 0)
{
for (var y = targets.Count - 1; y > -1; y--)
{
if (spaceObjs[y] == null)
{
spaceObjs.RemoveAt(y);
}
}
}
//Sort the list
spaceObjs.Sort(delegate(GameObject a, GameObject b)
{
return Vector3.Distance(player.position, a.transform.position).CompareTo
((Vector3.Distance(player.position, b.transform.position)));
});
}
Why not just use:
foreach(GameObject obj in spaceObjs)
{
if(obj == null)
{
spaceObjs.Remove(obj);
}
}
Instead of:
//try to remove nulls
if (spaceObjs.Count > 0)
{
for (var y = targets.Count - 1; y > -1; y--)
{
if (spaceObjs[y] == null)
{
spaceObjs.RemoveAt(y);
}
}
}
@TaleOf4Gamers_1
Modifying a container in the middle of a foreach is a big no-no.
@Cyrussphere
Are you sure your references are being marked null? If you just call Destroy(spaceObjs[index]), that’s not going to do it. You might want to check if spaceObjects[index].activeInHierarchy is false, and then remove it.
When I destroy a ship a can see it as Missing in the list which I assume is null, such as in the following screenshot.

I also checked in the piece of code that adds enemies to the list, AddEnemies() function. This also has a null check and then puts it in a another target list (Which I have another null cleaning function like spaceobjs that actually does work). Then I have an AddTarget() function that puts it into the spaceobjs list. I am wondering if it keeps getting re-added but I can’t find it in the logic. Here are the other two pieces of code
public void AddEnemies()
{
GameObject[] go = GameObject.FindGameObjectsWithTag("Enemy");
foreach (GameObject enemy in go)
{
if (enemy != null)
{
float dist = Vector3.Distance(enemy.transform.position, player.position);
if (dist < 500)
{
if (!targets.Contains(enemy))
{
targets.Add(enemy);
AddTarget(enemy);
}
}
else if (dist > 500)
{
if (targets.Contains(enemy))
{
targets.Remove(enemy);
RemoveTarget(enemy);
}
}
}
}
}
public void AddTarget(GameObject targetobj)
{
spaceObjs.Add(targetobj);
var newButton = Instantiate(TargetButton);
newButton.transform.SetParent(targetFormatter.transform, false);
TargetButton buttonScript = newButton.GetComponent<TargetButton>();
buttonScript.myOwner = targetobj;
}
*Edit: I lied, the targets List is also not clearing the nulls either
Can you share the code where you kill / destroy the object?
In your loop, enemy should never be null since you just found it with FindGameObjectsWithTag(). I think you’re confusing null with a destroyed / inactive game object.
I think I figured it out. When the enemy ship is destroyed it is Destroy(gameObject) to wipe it out completely. What I did was made a RemoveTarget function to just remove that item from the list and destroy the target button and then on the enemy Death function I reached out to this function which seems to successfully remove it. Since I have a handful of destructible items I was hoping the list cleaning would just take care of any destroyed objects but I may just need to use this function everywhere else. Here’s what they look like
//Function on nearbyobjs script
public void RemoveTarget(GameObject targetobj)
{
spaceObjs.Remove(targetobj);
foreach (Transform child in targetFormatter.transform)
{
var targetdata = child.GetComponent<TargetButton>().myOwner;
if (targetdata == targetobj)
{
Destroy(child.gameObject);
}
}
}
//function on enemy FSM script
public void DestroyEnemy()
{
objectlist.RemoveTarget(this.gameObject);
var offset = new Vector3(.05f, .05f, .05f);
isDead = true;
Instantiate(explosion, transform.position, transform.rotation);
Instantiate(wreck, transform.position + offset, transform.rotation);
hud.Hide();
Destroy(gameObject, 2);
}