Coroutines in monogame project

Can anyone explain to me step by step on how its done? Unity was able to do it, and I’ve heard of the process using IEnumerator and some kind of fancy iterator manipulation that calls methods with IEnumerator return type each frame from the last point it left off from.

Coroutines like those used in Unity are a part of C# 2.0, so they could be used in MonoGame, but really I have never seen anyone outside of Unity ever use them. The C# compiler creates a state machine behind the scenes to handle the case where it returns from the coroutine and has to jump back into it the next frame. From what I can tell, each Unity MonoBehaviour object has a list of currently active coroutines. Each call to MonoBehaviour.Update will iterate that coroutine list, stepping the IEnumerator and calling the coroutine until the IEnumerator has reached the end. It is then removed from the list.

The rest of the C# world has moved on. Async/await is the favoured approach these days, but the System.Threading.Tasks namespace has a lot of useful features as well.

Ah I see.
I have been abit iffy on using async/await because I heard it is very similar to creating Task objects. Which wouldn’t really be good in my case. Say I have an enemy, that enemy executes a set of actions at fixed intervals, using Tasks or async methods I could just await Task.Delay inside of while loop. But in the case of the separate thread running faster, or main thread pausing for whatever reason, this creates an unbalance that could result in things such as, threads modifying collections while a collection is in a foreach() loop, or things happening while the main thread has yet to catch up (Moving the game window pauses the main thread, Tasks don’t follow suit and just continue on).

But if async/await can work better, is there a way to implement it in a way that works similar to the old coroutine system? Where a method atleast has the illusion of being asynchronous but still bringing control back to the main thread? I have tried to do so, but no luck, I’m still abit new to C# so I may be doing it wrong.

You could implement your own state machine. This can be as simple as an enum that defines what state the enemy is in at that time. Each call to Update of the enemy runs a bit of code for that state. This code might change the state or leave it as is until the next call to Update where it runs that bit of code again.

enum EnemyState
{
    Idle,
    Walk,
    Attack,
}

class Enemy
{
    EnemyState _state;

    public void Update()
    {
        switch (_state)
        {
            case EnemyState.Idle:
                if (the player is in range)
                    StartAttack();
                else if (should we go somewhere)
                    StartWalk();
                break;
            case EnemyState.Walk:
                if (the player is in range)
                    StartAttack();
                else if (reached destination)
                    StartIdle();
                else
                    MoveForward();
                break;
            case EnemyState.Attack:
                if (the attack is finished)
                    StartIdle();
                break;
        }
    }

    void StartIdle()
    {
        // Start the idle animation
        // ...
        _state = EnemyState.Idle;
    }

    void StartWalk()
    {
        // Start the walk animation
        // ...
        _state = EnemyState.Walk;
    }

    void StartAttack()
    {
        // Start the attack animation
        // ...
        _state = EnemyState.Attack;
    }
}

Interesting concept, I never thought of doing it that way. I’ll try it in the future.

I usually lurk on the mailing list but this was intriguing enough for me to put in my two cents.

Coroutines are basically state machines, you advance from one part of the routine to another asynchronously Asynchronously meaning over multiple frames and not necessarily on different threads, however that’s the beauty of it. How the Coroutine is actually executed is abstracted away from you, and all you care about is that the function acts in a non blocking manner to the caller.

I’ve built a proof of concept here for a game I was working on some time ago. It is based off of the Unity Coroutine API, so if you’re familiar with that, you should feel right at home with this.

For most applications, using async/await is a better option. However, for games and their performance needs, you sometimes need to implement something that you have complete control over. The one advantage to my approach is that you are guaranteed that your routine will start execution on the next frame at the latest. You don’t have to wait for a thread scheduler or anything crazy, you just fire and forget knowing that everything is running in the main game loop.

To use it as is, the syntax is something like:

ICoroutineManager _routineManager;

public void DoMyAsyncThing()
{
   _routineManager.Run(DoSomethingAsync())
}

public IEnumerable DoSomethingAsync()
{
    Console.WriteLine("Starting");
    yield return Wait.Seconds(5);
    Console.WriteLine("Done");
}

Where CoroutineManager can be modified to inherit from a MonoGame’s GameComponent.

The source should mostly work, I haven’t tested it in a long time. It should get you most of the way to where you want to be though.

Below is one example of how to do the AI @KonajuGames demonstrated above.

public IEnumerable StartAI()
{
    while (!IsDead)
    {
       
       if (_state == EnemyState.Idle)
       {
                if (the player is in range)
                    StartAttack();
                else if (should we go somewhere)
                    StartWalk();
       }
       else if (_state == EnemyState.Walk)
       {
               if (the player is in range)
                   StartAttack();
               else if (reached destination)
                   StartIdle();
       }
       else if (_state == EnemyState.Attack)
       {
              if (the attack is finished)
                StartIdle();
       }
       yield Wait.Seconds(5); // <-- yielding will stop the routine from blocking the main thread
    }
}

You can do other things like yield from the AI behavior methods (like StartIdle, StartAttack etc).

I’m in sort of a hurry at the moment, but if you have any questions about the code feel free to ask.

With the help of someone who is also a veteran C# user, we were able to create a similar implementation to how you did it, just more compact in a way. Though in my game, there’s two types of Coroutines, one for outside of the main gameplay, and one for the main gameplay so that the task doesn’t continue running functions and making actions while the game is paused

Though thanks for posting this, it can be very useful for others who need that async feel.