Skip to content

Phases

Tecs divides its game loop into phases. Add systems to phases to run game logic at specific points: when the game starts, each frame update, frame render, and shutdown.

Love2D bindings

The Love2D integration provides these phases out of the box.

Phase groups

Tecs organizes phases into hierarchical groups:

StartupGroup

One-time initialization phases run when world:startup() is called.

  • PreStartup - Critical initialization before main startup
  • Startup - Main startup phase
  • PostStartup - Final setup after startup

MainGroup

The main game loop that runs every frame when world:update(dt) is called.

  • First - Very start of each frame (typically reserved for framework code)
  • PreUpdate - Before main update
  • FixedUpdateGroup - Fixed timestep loop (may run 0-N times per frame)
    • FixedFirst - Start of fixed update iteration (typically reserved for framework code)
    • FixedPreUpdate - Preparation for game logic
    • FixedUpdate - Main game logic and physics
    • FixedPostUpdate - After game logic
    • FixedLast - End of fixed update iteration (typically reserved for framework code)
  • Update - Variable timestep presentation update
  • PostUpdate - After presentation, before rendering
  • RenderGroup - Rendering phases
    • RenderFirst - Start of rendering (typically reserved for framework code)
    • PreRender - Render preparation
    • Render - Main rendering
    • PostRender - Post-processing and effects
    • RenderLast - End of rendering (typically reserved for framework code)
  • Last - Very end of each frame

ShutdownGroup

One-time cleanup phases run when world:shutdown() is called.

  • PreShutdown - Preparation for shutdown
  • Shutdown - Main shutdown phase
  • PostShutdown - Final cleanup

Fixed vs variable phases

  • Fixed timestep phases (FixedUpdate and related): used for physics, game logic, AI, and anything affecting gameplay that should feel consistent regardless of speed of the computer.
  • Variable timestep phases (Update and related): used for visual presentation, animations, camera smoothing, UI effects, and generally anything else that looks or feels better the faster the computer.

Using phases

Access phases through tecs.phases:

teal
local tecs = require("tecs")

-- Add a system to the Update phase
world:addSystem({
    phase = tecs.phases.Update,
    run = myUpdateSystem
})

-- Add a physics system to the fixed timestep
world:addSystem({
    phase = tecs.phases.FixedUpdate,
    run = myPhysicsSystem
})

Managing phases

These methods are available on every World.

MethodDescription
world:enablePhaseEnable a phase or phase group.
world:disablePhaseDisable a phase or phase group.
world:registerPhaseRegister a custom phase with the world's pipeline.
world:runPhaseRun a phase or phase group explicitly.

Enabling and disabling phases

You can dynamically enable and disable phases to control which systems run:

teal
-- Disable a phase (and all its systems)
world:disablePhase(tecs.phases.RenderGroup)  -- Disable all rendering

-- Re-enable a phase
world:enablePhase(tecs.phases.RenderGroup)

-- Disable fixed timestep when paused
world:disablePhase(tecs.phases.FixedUpdateGroup)

Disabling parent phases

Disabling a parent phase (like RenderGroup) also disables all its children phases.

Running specific phases

You can explicitly run a specific phase using world:runPhase():

teal
-- Run only the Render phase
world:runPhase(tecs.phases.Render)

-- Run the entire RenderGroup
world:runPhase(tecs.phases.RenderGroup)

Disabled phases behavior

When you disable a phase:

  • It won't run during the normal game loop
  • You can still explicitly run it with world:runPhase()
  • If you disable a parent phase, its child phases remain disabled even when you explicitly run the parent
teal
-- Disable all rendering
world:disablePhase(tecs.phases.RenderGroup)

-- This runs RenderGroup but NOT its children (PreRender, Render, PostRender, etc.)
world:runPhase(tecs.phases.RenderGroup)

-- To run a specific child phase when parent is disabled:
world:runPhase(tecs.phases.Render)  -- This works even though RenderGroup is disabled

world:enablePhase

Enables a phase or phase group so it runs during normal pipeline execution.

teal
function World:enablePhase(phase: Phase)

Parameters:

  • phase: Phase or phase group to enable.

world:disablePhase

Disables a phase or phase group during normal pipeline execution. Disabling a parent phase also disables its child phases.

teal
function World:disablePhase(phase: Phase)

Parameters:

  • phase: Phase or phase group to disable.

world:registerPhase

Registers a custom phase with the world's pipeline. Use this when an extension or custom pipeline adds phases outside the built-in tecs.phases tree.

teal
function World:registerPhase(phase: Phase)

Parameters:

  • phase: Phase to register.

world:runPhase

Runs a phase or phase group immediately. Disabled child phases are still skipped when running a disabled parent group; run a child phase directly if you need to bypass the parent.

teal
function World:runPhase(phase: Phase, dt?: number)

Parameters:

  • phase: Phase or phase group to run.
  • dt: Optional delta time passed to systems in that phase. Defaults to 0.