Skip to main content

Timers & Delays

Need something to happen later, or on a repeating schedule? Here's how to handle time-based logic in HELIX.

One-Shot Delaysโ€‹

Run code after a specified delay:

Blueprintโ€” One-Shot TimerScroll to zoom ยท Drag to pan ยท Drag nodes to move
Event BeginPlaySet Timer by EventEventTime3.0LoopingfalseReturn ValueOnDelayCompletePrint StringIn String"Timer fired!"

Repeating Timersโ€‹

Run code on a regular interval:

Blueprintโ€” Repeating TimerScroll to zoom ยท Drag to pan ยท Drag nodes to move
Event BeginPlaySet Timer by EventEventTime1.0LoopingtrueReturn ValueOnTimerTickPrint StringIn String"Tick!"

Use Clear Timer by Handle with the return value from Set Timer by Event to stop a repeating timer.

Coroutines in Luaโ€‹

Lua coroutines let you write sequential-looking code that pauses and resumes across frames:

function M:ReceiveBeginPlay()
-- Start a coroutine
self.SpawnRoutine = coroutine.create(function()
for i = 1, 5 do
self:SpawnEnemy(i)
print("Spawned enemy " .. i .. ", waiting...")
coroutine.yield() -- pause until resumed
end
print("All enemies spawned!")
end)

-- Resume it every 2 seconds
self.TimerHandle = Timer.SetInterval(function()
if coroutine.status(self.SpawnRoutine) ~= "dead" then
coroutine.resume(self.SpawnRoutine)
else
Timer.ClearInterval(self.TimerHandle)
end
end, 2000)
end

Promises in JavaScriptโ€‹

For complex async flows, use Promises or async/await:

function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

function waitForPlayers(minPlayers) {
return new Promise((resolve) => {
const handle = setInterval(() => {
// Check connected players (example โ€” adjust to your game logic)
const count = getConnectedPlayerCount();
if (count >= minPlayers) {
clearInterval(handle);
resolve(count);
}
}, 500);
});
}

async function startGame() {
console.log("Waiting for players...");
const count = await waitForPlayers(4);
console.log(`${count} players ready. Starting!`);

await delay(3000); // 3 second countdown
Helix.emit("GameStarted");
}

Tipsโ€‹

  • Timer values in the Lua Timer API use milliseconds (1000 = 1 second). UE's built-in timer nodes use seconds.
  • Always store timer handles and clear them when your actor is destroyed. Orphaned timers cause bugs that are tough to track down.
  • Avoid running heavy logic on fast intervals (< 100ms). If you need per-frame updates, use Tick / ReceiveTick instead.
  • The Blueprint Delay node is convenient but pauses that entire execution thread. For multiple independent delays, use separate timer handles.
โœจ