skip to Main Content

I’m using a monoGame template in Visual Studio, and I’m making an endless runner (similar to Chrome Dino).
In the LoadContent class I’ve used Enqueue to put my obstacles into a Queue list.
Note: I’ve only given the code for the first obstacle because the code for the others is exactly the same 🙂

Here’s my Queue code:

Queue<Texture2D> obstacles = new Queue<Texture2D>();

And my code in LoadContent to add my obstacles to the list:

obstacles.Enqueue(obstacle1);

Then in my Update class, I have the following code, which is where the error is:

foreach (var obstacle in obstacles)
{
    ob1X--;

    if(ob1X + 20 <= 0)
    {
        obstacles.Dequeue();
    }
}

when I run the code, it highlights the word in and throws the error:

Exception Unhandled
System.InvalidOperationException: ‘Collection was modified; enumeration operation may not execute.’

Am I doing something wrong, or am I missing an inportant part?

I got advised to use this method to make the obstacles come onto the screen, but this error is stopping me from continuing. Please help!

2

Answers


  1. Chosen as BEST ANSWER

    After a bit of researching and trial and error, I've discovered that you can't modify the contents of the queue within a foreach loop. To elaborate, the error was getting thrown because I was trying to Dequeue within the foreach loop. This code isn't allowed:

    foreach (var obstacle in obstacles)
    {
        ob1X--;
    
        if(ob1X <= 0)
        {
            obstacles.Dequeue();
        }
    }
    

    So what I did was take the if statement out of the foreach and put it under the loop. With just the obstacles.Dequeue(); , it was telling me the queue was empty. I had to Enqueue it after I Dequeue'd it for this to work.

    NOTE: the if statement is saying "when the obstacle reaches the left of the screen, take it off the queue, move it back to the right of the screen and add it back to the queue." This set-up will let me modify what comes onto the screen.

    My final code looks like this:

    foreach(var obstacle in obstacles)
    {
        ob1X--;
    }
    
    if(ob1X <= 0)
    {
        obstacles.Dequeue();
        ob1X = viewportWidth;
        obstacles.Enqueue(obstacle1);
    }
    

    I found this web page very helpful in understanding how Queues work, and it's not too technical to cause confusion! https://codebuns.com/csharp-advanced/queue/

    Hopefully this will help anyone else who is in the same situtation :)


  2. Your answer seems overly complicated, you do not need to be using a foreach loop at all then as it seems you are simply minusing the number of obstacles from the viewport width?

    If this is the case then you will be doubling the memory required to store obstacles as each obstacle is assigned to obstacle in your loop.

    ob1X -= obstacles.Count();
    
    if(ob1X <= 0)
    {
        obstacles.Dequeue();
        ob1X = viewportWidth;
        obstacles.Enqueue(obstacle1);
    }
    

    Your code in your answer also doesn’t match you OP where ob1X + 20 has to be less than 0 (a better way to write it would be obj1X < -20)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search