Skip to content

t1k:cocos:playable:lifecycle

FieldValue
Moduleplayable
Version0.5.6
Efforthigh
Tools

Keywords: ads, cocos, component, GameLifecycleManager, lifecycle, playable

/t1k:cocos:playable:lifecycle

GameLifecycleManager — Non-Component Lifecycle System

Section titled “GameLifecycleManager — Non-Component Lifecycle System”

Drives Tick/FixedTick/LateTick on plain TS classes that don’t extend Cocos Component. Add GameLifecycleManager as a component on a persistent scene node. See also: t1k-cocos-playable-signalbus, t1k-cocos-playable-async-utilities.

Import paths:

  • db://assets/PLAGameFoundation/gameLifecycle/GameLifecycleManager
  • db://assets/PLAGameFoundation/gameLifecycle/LifecycleDecorator
  • db://assets/PLAGameFoundation/gameLifecycle/interfaces/I*
InterfaceMethod signatureCalled when
IInitializableInitialize(): voidImmediately on Register()
ITickableTick(dt: number): voidEvery frame (via Cocos update)
IFixedTickableFixedTick(fixedDt: number): voidFixed timestep accumulator (default 0.02s / 50 FPS)
ILateTickableLateTick(dt: number): voidAfter all Ticks (via Cocos lateUpdate)
IDisposableDispose(): voidOn Unregister() or scene destroy

A class can implement any combination. Register() detects which interfaces are present via duck-typing (isType checks for method name existence).

Auto-instantiates and registers the class when GameLifecycleManager.onLoad() runs. No-arg constructor required.

import { RegisterLifecycle } from "db://assets/PLAGameFoundation/gameLifecycle/LifecycleDecorator";
import { IInitializable, ITickable, IDisposable } from "db://assets/PLAGameFoundation/gameLifecycle/interfaces/...";
@RegisterLifecycle()
export class MySystem implements IInitializable, ITickable, IDisposable {
Initialize(): void {
// setup — called once at scene start
}
Tick(dt: number): void {
// runs every frame
}
Dispose(): void {
// cleanup on scene destroy
}
}

Use when you need constructor args or runtime control:

const system = new MySystem(someArg);
GameLifecycleManager.Instance.Register(system);
// Later, to stop ticking and call Dispose:
GameLifecycleManager.Instance.Unregister(system);

The manager accumulates delta time and calls FixedTick at a fixed rate:

// Default: 0.02s (50 Hz). Change at runtime:
GameLifecycleManager.Instance.SetFixedTimeStep(1 / 30); // 30 Hz
GameLifecycleManager.Instance.GetFixedTimeStep();

FixedTick receives the configured fixedDeltaTime, not the accumulated surplus.

The manager uses duck-typing — not instanceof — to check interfaces:

// Internal implementation (for reference):
private isType<T>(obj: any, methodName: string): obj is T {
return methodName in obj;
}

This means TypeScript interfaces are checked at runtime by method presence. Ensure method names match exactly (Tick, FixedTick, LateTick, Initialize, Dispose).

console.log(GameLifecycleManager.Instance.GetDebugInfo());
// Prints counts for each collection + fixedTimeStep

When to Use Lifecycle Manager vs Cocos Component update()

Section titled “When to Use Lifecycle Manager vs Cocos Component update()”
ScenarioUse
Pure logic / service class (no Node)@RegisterLifecycle() + interfaces
Node-attached behaviourCocos Component with update()
Physics-like deterministic stepIFixedTickable
Camera follow / post-processILateTickable
One-time setup with no tickingIInitializable only
Cross-system service needing frame updatesITickable via lifecycle manager
  • Implementing tick() (lowercase) instead of Tick() — manager checks exact name; the method is silently ignored.
  • Using @RegisterLifecycle() on a class with constructor arguments — manager calls new ClassConstructor() with no args; use manual Register() instead.
  • Multiple GameLifecycleManager components in the scene — the second one self-destructs. Keep exactly one on a persistent node.
  • Forgetting IDisposable on systems holding signal subscriptions or timers — causes leaks on scene reload.
  • Cocos lifecycle order: onLoad → onEnable → start → update — wiring listeners in start instead of onEnable skips the first re-enable cycle.
  • onDisable fires on scene close before onDestroy — release resources in onDestroy, not onDisable, to survive scene navigation.
  • update is called even on disabled components in some Cocos versions — guard with this.enabled or migrate to lateUpdate.