Developer Timers Coroutines
Scheduling work without freezing the game. (Oxide equivalent: “Timers” + “Coroutines”.)
Registered once in LuaCoroutineScheduler (src/gregCore.SDK/Lua/LuaCoroutineScheduler.cs), pumped every OnUpdate(dt):
greg.wait(5, function() greg.ui.log_info("Once, after 5 seconds")end)
greg.every(60, function() greg.ui.log_info("Every 60 seconds")end)
greg.start_coroutine(function() greg.ui.log_info("Step 1") coroutine.yield(greg.WAIT) -- return-wait values cooperate with the scheduler greg.ui.log_info("Step 2")end)Rules:
greg.wait(seconds, callback)— one-shot.greg.every(seconds, callback)— repeating.greg.start_coroutine(fn)— coroutine withcoroutine.yield()/ return-wait values.- Never
while true do … endwithout yielding — you block the main thread. Never log per-frame inon_update. - Timer callbacks run on the main thread, so game-API calls are safe inside them.
- Per-frame: override
OnUpdate(dt)inGregMod; keep it allocation-free (no reflection, noFindObjectsOfType— cache and throttle: 1 s / 2 s / 0.1 s / 30 s tiers perdocs/modding/harmony-il2cpp.md). - Deferred/queued:
GregOperationQueuefor bursts;GregMainThreadDispatcherto marshal back to the main thread. - Governed:
GregPerformanceGovernor+GregResourceMonitor+GregPerformancePatches(cullingWorldCanvasCuller, technician/footstep/indicator throttles) keep background work bounded.
Anti-patterns
Section titled “Anti-patterns”| Do | Do not |
|---|---|
greg.every(30, poll) for polling |
on_update with a log line |
Cache Type/MethodInfo, throttle scans |
Reflect or scan the scene every frame |
| Yield in coroutines | Busy-wait or sleep the main thread |
wait for one-shots |
A repeating timer you never cancel |