The root of your trouble lies in the necessity to add or remove elements while iterating over collection. You should keep these things to a minimum, but sometimes it just can't be avoided.
Making copies every time you want to iterate a collection is often not an option due to performance reasons.
Now there are two possibilities: your loop and your adds|removals are either on the different threads or on the same thread.
If it's the multithreaded case, Tyn gave you pointers on what to do. One simple solution would be to synchronize all access to the collection, using some object as the monitor. It may be slow if your collection is large, because threads wanting to add or remove something will be blocked while waiting for iteration to complete:
// For loop
for (...) // Iterations here
//Now when other thread wants to add or remove something,
// it needs to synchronize too:
// Somewhere on the other thread
You can use ConcurrentHashMap, but be prepared to face the consequences. I can remember only that its iterators sometimes reflect adds or removals occured since the iterator construction and sometimes they don't, but there should be plenty of other subtle things, maybe like "get" operation placing a memory barrier. So if you add and remove things very rarely, it may be better to use a "copy on write" approach.
Funny thing is, unless your threaded operations with objects on the loop are slow as hell (and usually they shouldn't be), it may actually be faster to keep them single-threaded. I deduced that if there is a bunch of monsters with some petty Update() functions, and you want to process their little functions on different threads, you're in for a trouble :) So keep in mind that multithreading just for the sake of it eats up your CPU with context swaps and supply you with livelocks and starvation issues here and there.
If it's the single thread case, then removal of the elements in the collection being iterated won't work, so there are two another options:
- The most usable option: add a queue of objects to add|remove, and process them out of your loop.
- If you only need to remove a current object of an iteration phase, it is possible to use an indexed collection with a for loop, and then remove current element while adjusting loop counter. Or just loop backwards.
Just for clarity, example for the first approach:
while ((objectToRemove = objectsToRemove.Pop()) != null)
foreach(var gameObject in allGameObjects)
// process your objects here as always, but if you need to
// add or remove an object, push it to the appropriate queue.
And example for the second approach:
for (int i = 0; i < allGameObjects.Count; i++)
// to remove an object, do something like