arcade2d
Class

PhysicsDebugRenderer

physics/physics-debug-renderer.ts:86

Extends AbstractWorldComponent<PhysicsDebugRendererDeps>

A world-scoped debugging overlay that draws the outline of every collider in the PhysicsWorld on top of the scene. It exists to answer the question that comes up constantly when wiring up physics — "where does the engine actually think this body is?" — by making the otherwise-invisible simulation geometry visible, so a collider that's the wrong size, offset from its sprite, or rotated unexpectedly is obvious at a glance instead of something you infer from misbehaviour.

On/off at startup, not toggleable

The renderer is opt-in by registration: add it to a world's component factory and the overlay is on; leave it out and there is zero cost. There is deliberately no runtime toggle — wire it in (or behind your own build flag) when you want it. Like PhysicsWorld, it is never auto-attached.

How it draws

Each frame, in post-update — after PhysicsWorld has stepped the simulation in pre-update, so every body's transform is settled — the renderer asks Rapier for a fresh set of debug line segments (its built-in debugRender, the same data Rapier's own debuggers use) and strokes them into a single Pixi Graphics overlay. The overlay is a child of the Scene, so it inherits the camera transform and the outlines stay locked to the bodies as the camera pans, zooms, and rotates. It is given a very high zIndex (and turns on the scene container's child sorting) so the outlines sit above the filled body graphics they trace — including bodies spawned at runtime after this component was added.

By default the segments are tinted with Rapier's own per-collider colours, which distinguish awake from sleeping bodies and sensors from solid colliders. Pass PhysicsDebugRendererOptions.color to override them with a single flat colour (and take the cheaper single-stroke draw path).

Example

import {
  Game, initPhysics, PhysicsWorld, PhysicsDebugRenderer,
} from '@arcade2d/engine';

const game = await Game.bootstrap({ canvas: { fill: 'window' } });
await initPhysics();

const DEBUG_PHYSICS = true; // flip per build/environment

const world = game.createWorld({
  components: (world) => ({
    physics: () => new PhysicsWorld(world, { gravity: { x: 0, y: 980 } }),
    // Registering the component is the on switch; omit it and there's no cost.
    ...(DEBUG_PHYSICS
      ? { physicsDebug: () => new PhysicsDebugRenderer(world) }
      : {}),
  }),
});

Constructors

#
constructor(host: World, options: PhysicsDebugRendererOptions): PhysicsDebugRenderer

Parameters

Properties

#
enabled: boolean

Per-component gate on the three update hooks (onPreUpdate, onUpdate, onPostUpdate). When explicitly false, the engine skips all three for this component during the host's tick — useful for temporarily pausing behaviour (e.g. a freeze powerup) without removing the component and losing its internal state.

Does not gate onAdded or onDestroy; those always fire so a host can never end up with a half-attached component.

readonly #
host: World

The host this component is attached to. Stored read-only; subclasses access it as this.host directly, or through the tier-appropriate aliases (this.world, this.game) on the per-tier abstract bases.

Accessors

readonly #
game: Game

The Game the host world belongs to. Always non-null — the world's game field is a mandatory construction argument, not an option.

readonly #
raw: Graphics

Direct access to the underlying Pixi Graphics overlay.

Use with care. raw is an intentional escape hatch — for tuning the overlay's blend mode, alpha, or filters beyond what this component models. Code that touches raw is coupled to Pixi's public API; prefer PhysicsDebugRendererOptions where it covers your need.

readonly #
world: World

The World this component is attached to — identical to AbstractComponent.host at this tier, exposed under the world name so subclass code reads the same on every tier.

Methods

#
onAdded(__namedParameters: PhysicsDebugRendererDeps): void

Mounts the overlay into the scene and enables child sorting on the scene container so the high-zIndex overlay reliably draws above the bodies it traces.

Parameters

  • __namedParameters PhysicsDebugRendererDeps

Returns

void
#
onDestroy(): void

Detaches and frees the overlay. Safe to call even if onAdded never ran.

Returns

void
#
onPostUpdate(_update: WorldUpdate, __namedParameters: PhysicsDebugRendererDeps): void

Redraws every collider outline for the current, settled simulation state. Runs in post-update so PhysicsWorld's pre-update step has already advanced the bodies this frame.

Parameters

  • _update WorldUpdate
  • __namedParameters PhysicsDebugRendererDeps

Returns

void
#
onUpdate(_update: WorldUpdate, _deps: PhysicsDebugRendererDeps): void

Lifecycle hook for the main update phase. Called once per world tick, after every component's onPreUpdate and before any onPostUpdate.

Parameters

Returns

void
#
resolveDependencies(resolver: WorldDependencyResolver): PhysicsDebugRendererDeps

Declares the world-tier dependencies on the Scene and the PhysicsWorld.

Parameters

Returns

PhysicsDebugRendererDeps

Throws

EngineError with code ErrorCode.WORLD_COMPONENT_DEPENDENCY_MISSING when the world has no PhysicsWorld to read colliders from. (The Scene is auto-attached, so only the physics dependency is realistically absent.)

ESC