Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commit3bb1da2647

README.md

autoTick

Opt-in tick loop for zinput. Spawns a task.spawnSystem worker that invokes a registered tick function (Zin.tick) once per frame while the input layer has work, and waits for the input layer's next change (__waitChange("input"): an input event, a moved input snapshot, an armed observation, a mapping-layer mark) once a tick finds it at rest (Zin.atRest()), so code-mode snippets and tests without a host script component still drive the stateful subsystems — live binding dispatch, the touch overlay, the emulation floor, axes, chords, rebind, action handlers, event subscribers. task.spawnSystem (not task.spawn) makes the loop system-owned, so it keeps ticking while the editor pauses gameplay.

The first real input read arms this worker on its own. A host script component can also call Zin.tick(dt) from its update(dt) hook, and autoTick.start can be called directly; all three are idempotent alongside each other.

Exports

  • M.start() -> boolean — spawn the worker if not already running. Returns true when a new loop was started.
  • M.stop() — flag the loop to exit on its next yield. No-op if not running.
  • M.isRunning() -> boolean — current status.
  • M._setTickFn(fn: (number?) -> ()) — internal hook. Called once by zinput/init.luau to register Zin.tick.
  • M._setLastTickFrameIdFn(fn: () -> number) — internal hook. Wires the frame-id accessor so the worker can dedup itself against explicit ticks within the same engine frame.
  • M._setAtRestFn(fn: () -> boolean) — internal hook. Wires Zin.atRest, the predicate the worker reads after each tick to decide whether to wait for the input layer's next change.

Usage

local Zin = require("@builtin::modules.zinput")

-- One-shot test / code-mode setup:
Zin.autoTick.start()

-- ... later ...
Zin.autoTick.stop()

Notes

  • Single-flight: calling start() twice is a no-op — there is at most one worker per VM.
  • Cross-coroutine dedup: when an explicit Zin.tick ran in the same engine frame, the worker skips that frame so onHeld handlers and event subscribers don't double-fire.
  • Module-local _running survives Luau require-cache reload, so a re-required autoTick.module still reports the loop is live. restart_instance resets the VM and clears everything.
  • start() raises if _setTickFn hasn't been wired yet — always require("@builtin::modules.zinput") first.