feat: added a wip nested coroutine manager

This coroutine manager allows for nested IEnumerators, however it is experimental at the moment.
This commit is contained in:
2026-04-07 18:12:01 +03:00
parent b713fe4f12
commit 6d8ba5c80c
3 changed files with 91 additions and 2 deletions

View File

@@ -0,0 +1,9 @@
using System.Collections;
namespace Engine.Core;
public interface ICoroutineManager
{
IEnumerator StartCoroutine(IEnumerator enumerator);
void StopCoroutine(IEnumerator enumerator);
}

View File

@@ -0,0 +1,80 @@
using System.Collections;
using System.Collections.Generic;
namespace Engine.Core;
public class NestedCoroutineManager : Behaviour, IUpdate, ICoroutineManager
{
private readonly List<CoroutineStack> stacks = [];
private readonly Pool<CoroutineStack> pool = new(() => new());
public IEnumerator StartCoroutine(IEnumerator enumerator)
{
CoroutineStack stack = pool.Get();
stack.EntryPoint = enumerator;
stack.Stack.Push(enumerator);
stacks.Add(stack);
return enumerator;
}
public void StopCoroutine(IEnumerator enumerator)
{
for (int i = 0; i < stacks.Count; i++)
if (stacks[i].EntryPoint == enumerator)
{
RemoveCoroutineAt(i);
return;
}
}
private void RemoveCoroutineAt(int i)
{
stacks[i].Reset();
stacks.RemoveAt(i);
}
void IUpdate.Update()
{
for (int i = stacks.Count - 1; i >= 0; i--)
{
Stack<IEnumerator> stack = stacks[i].Stack;
if (stack.Count == 0)
{
RemoveCoroutineAt(i);
continue;
}
IEnumerator top = stack.Peek();
if (top.Current is ICoroutineYield coroutineYield && coroutineYield.Yield())
continue;
if (top.Current is IEnumerator nested)
{
stack.Push(nested);
continue;
}
if (!top.MoveNext())
{
stack.Pop();
if (stack.Count != 0)
stack.Peek().MoveNext();
continue;
}
}
}
private class CoroutineStack
{
public IEnumerator EntryPoint = null!;
public Stack<IEnumerator> Stack = new();
public void Reset() { EntryPoint = null!; Stack.Clear(); }
}
public NestedCoroutineManager() => Priority = int.MinValue;
}