-1

For some reason I have looked at lots of posts and still I don't know how to fix this. In the update method of my game, I have a for loop that updates all the existing GameObjects.

private static void update() {
    for (GameObject g : GameObjectManager.getGameObjects()) {
        g.update();
    }
    canvas.repaint();
}

It says there is a ConcurrentModificationException error at the line of the for loop. I have tried, like some people said, to get the iterator of the game object list and then use that, but it still doesn't work. Even though it says the error line is at the for loop, when I remove g.update there is no more error. EDIT: I found the error. It adds a game object to the list in the GameObjectManager.registerGameObject(). The only other class that uses the update is this:

public class PaintCanvas extends JPanel {
    private static final long serialVersionUID = 6718161148154673832L;

    {
        this.setDoubleBuffered(true);
        this.setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.RED);
        for (GameObject go : GameObjectManager.getGameObjects()) {
            g.fillRect(go.getPosition().getX(), go.getPosition().getY(), 30, 30);
        }
    }
}

The only update method is this:

@Override
public void update() {
    Random r = new Random();
    int spawn = r.nextInt(100);
    // 5% Chance to spawn
    if (spawn <= 5) {
        Spawner s = new Spawner();
        s.setPosition(new Point(4, 50));
    }
}
MCMastery
  • 3,099
  • 2
  • 20
  • 43
  • The problem is not that the GameObjects are modified, but the list itself, while iterating over it: GameObjectManager.getGameObjects() <---- the List that is returned by this call. Maybe g.update() removes or adds other GameObjects from this list? – Chrisport Nov 02 '14 at 19:59

2 Answers2

2

You can't modify a list while iterating it. One of your game object's update methods must be adding or removing items.

You can iterate over a copy:

for (GameObject g : new ArrayList(GameObjectManager.getGameObjects())) {
    g.update();
}

Or use a normal for loop, here objects can be added safely, but not removed:

List<GameObject> objects = GameObjectManager.getGameObjects();
int size = objects.size();
for(int i = 0; i < size; i++) {
    GameObject g = objects.get(i);
    g.update();
}

Or fix GameObjectManager.registerGameObject() to add to a temp list, not the main list and move them to the main list just before the existing code. The same could be done for removals.

GameObjectManager.promoteNewGameObjects(); //promote objects added in the last frame
for (GameObject g : GameObjectManager.getGameObjects()) {
    g.update(); //as before
}
weston
  • 54,145
  • 21
  • 145
  • 203
2

In this situation, this exception will be thrown when something is trying to modify an array whilst something else is currently using it (iterating over it etc). Like, a new monster is spawned on the map and added to some monster list, while the gameloop is currently iterating over said list. In your GameObjectManager class, what are you using to store the GameObject's? If it's a normal list, you should consider changing it to CopyOnWriteArrayList or any other Thread-Safe list, it should fix the problem.

FruitAddict
  • 2,042
  • 15
  • 16
  • I found that the error is actually when it adds a game object to the list. (Just a simple List.add). How do I change that line to be thread-safe? – MCMastery Nov 02 '14 at 20:28
  • You could either use Thread-safe lists (like CopyOnWriteArrayList) or synchronize those error-throwing blocks yourself. The second option is way more complicated, read about synchronizing and concurrency if you want to do it manually. Synchronization basically gives a ,,key'' to an object to some method as long as it works on it, and other methods cant access that object until this key is available again. – FruitAddict Nov 02 '14 at 20:34