Description
This is a partial port of the MEC Free asset for Godot 4.x .NET (C#) published with permission under the MIT license.
MEC provides Unity-style IEnumerator coroutines with zero per-frame garbage generation.
Original source by Teal Rogers at Trinary Software.
Installation
- Download the latest commit or the stable Release version.
- Place the
addons
folder into your project root. - Build the project solution under
MSBuild > Build > Build Project
Key Features
This is a non-exhaustive list, check the original documentation for a more comprehensive overview. Usage is largely unchanged, aside from changes to the naming convention.
Yielding
MEC has the following functions to yield on.
Timing.WaitForOneFrame
- Yields for one frameTiming.WaitForSeconds(seconds)
- Yields for the given number of secondsTiming.WaitUntilDone(anotherCoroutineHandle)
- Yields until the passed coroutine has ended
IEnumerator<double> MyCoroutine()
{
yield return Timing.WaitForOneFrame;
GD.Print("One frame has passed");
yield return Timing.WaitForSeconds(2.0);
GD.Print("Two seconds have passed");
yield return Timing.WaitUntilDone(Timing.RunCoroutine(DoSomethingElse());
GD.Print("Finished doing something else");
}
CancelWith
Because coroutines do not by default live on the node that started them, they will keep going after the node is freed. By using CancelWith, coroutines can be automatically cancelled when an object they depend on is lost.
Timing.RunCoroutine(MyCoroutine().CancelWith(myNode));
// Overloads with up to three objects are provided
Timing.RunCoroutine(MyCoroutine().CancelWith(myNode1, myNode2, myNode3));
Update Segments
When starting a coroutine, you can specify the time segment in which it runs.
Process
- Updates just before _ProcessPhysicsProcess
- Updates just before _PhysicsProcessDeferredProcess
- Updates at the end of the current frame
Timing.RunCoroutine(MyCoroutine(), Segment.PhysicsProcess);
Tags
Coroutines may be grouped by a string tag for easy global management.
Timing.RunCoroutine(MyCoroutine(), "myTag");
Timing.RunCoroutine(MyOtherCoroutine(), "myTag");
// Kill both coroutines above
Timing.KillCoroutines("myTag");
Notable Differences
If you used MEC with Unity in the past, or are using the Unity documentation for reference, there are a few things to keep in mind.
Doubles
Godot uses double
for its scalars, so coroutines make use of IEnumerator<double>
.
Naming
Names have been changed to match Godot terminology, most notably:
Update
->Process
GameObject
->Node
LateUpdate
->DeferredProcess
Execution Order
To avoid ambiguous execution order at runtime depending on the tree layout, all Timing
instances start with a ProcessPriority
and ProcessPhysicsPriority
of -1. This means coroutines will update before all regular nodes by default.
Missing Features
A handful of features have not been ported from the original MEC, such as SlowUpdate, and using WaitUntilDone on non-coroutines. These may be ported over in the future. Pull requests welcome!
Contribution
If you spot a bug while using this, please create an Issue.
License
Copyright (c) 2023-present, Teal Rogers, Isar Arason (WeaverDev)