Skip to main content

Physics2D

APJS Script API reference for the Physics2D class.

TypeNameInterface Description
Variablesgravity: Vector2f

Function: Global 2D gravity acceleration in m/s^2. Default is (0, -9.8), simulating Earth-like gravity pulling downward. Set to to disable global gravity. Per-body gravity can be controlled via and . Not reset on record start — retains the value you set.

VariablestimeSpeed: number

Function: Scales how fast the 2D physics simulation steps forward. 1.0 runs at normal simulation speed, 0.5 runs in slow motion, and 0.0 stops physics updates. Not reset on record start.

Static Functionsraycast2D(ray: Ray, maxDistance: number, nearest: boolean, layerMask?: LayerSet): RaycastHit2D[]

Function: Casts a ray through the 2D physics world and returns the matching hits.

Parameters

ray: The ray with origin and direction. Origin and direction are interpreted in 2D world XY space; Z is ignored. Direction must be non-zero.

maxDistance: Maximum cast distance in 2D world units. Must be positive.

nearest: If true, returns only the closest hit. If false, returns all hits along the ray.

layerMask: Optional layer mask to filter which layers can be hit. If omitted, all layers are tested.

Returns Array of . Empty array if nothing was hit.

Examples

raycast2D(ray: Ray, maxDistance: number, nearest: boolean, layerMask?: LayerSet): RaycastHit2D[]

// Shoot a ray downward from (100, 200) to detect what's below
const ray = new APJS.Ray(new APJS.Vector3f(100, 200, 0), new APJS.Vector3f(0, -1, 0));
const hits = APJS.Physics2D.raycast2D(ray, 50, true);
if (hits.length > 0) {
console.log("Hit at:", hits[0].point);
}

Use Case

Example 1 — Tap-triggered global slow-motion for 2D physics. Sets APJS.Physics2D.timeSpeed = 0.3 for 0.5 s real-time on Touch.Began, then restores to 1.0.

@component()
export class SlowmoController extends APJS.BasicScriptComponent {
@serializeProperty
slowFactor: number = 0.3;

@serializeProperty
durationSeconds: number = 0.5;

@serializeProperty
oneShot: boolean = true;

private touchHandler: ((event: APJS.IEvent) => void) | null = null;
private elapsed: number = 0;
private slowmoActive: boolean = false;
private slowmoEnd: number = 0;
private done: boolean = false;

onStart(): void {
this.touchHandler = (event: APJS.IEvent) => {
const td = event.args[0] as APJS.TouchData;
const canTrigger = td.phase === APJS.TouchPhase.Began
&& !this.slowmoActive
&& (!this.oneShot || !this.done);
if (canTrigger) {
APJS.Physics2D.timeSpeed = this.slowFactor;
this.slowmoActive = true;
this.slowmoEnd = this.elapsed + this.durationSeconds;
}
};
APJS.EventManager.getGlobalEmitter().on(APJS.EventType.Touch, this.touchHandler);
}

onUpdate(dt: number): void {
this.elapsed += dt;
if (this.slowmoActive && this.elapsed >= this.slowmoEnd) {
APJS.Physics2D.timeSpeed = 1.0;
this.slowmoActive = false;
if (this.oneShot) this.done = true;
}
}

onDestroy(): void {
if (this.touchHandler) APJS.EventManager.getGlobalEmitter().off(APJS.EventType.Touch, this.touchHandler);
APJS.Physics2D.timeSpeed = 1.0;
}
}

Example 2 — Play a sound effect when a 2D physics object collides — uses CollisionEvent2D.Enter on collider's object emitter

@component()
export class CollisionSoundEffect extends APJS.BasicScriptComponent {
@serializeProperty
sfxPlayer!: APJS.SceneObject;

private sfxAudio!: APJS.AudioComponent;
private collider!: APJS.BoxCollider2D;
private initialized = false;
private collisionCallback!: (event: APJS.IEvent) => void;

onUpdate(dt: number): void {
if (this.initialized) return;
if (!this.sfxPlayer) return;

this.sfxAudio = this.sfxPlayer.getComponent("AudioComponent") as APJS.AudioComponent;
// Get any 2D collider on this object (BoxCollider2D or CircleCollider2D)
this.collider = this.getSceneObject().getComponent("BoxCollider2D") as APJS.BoxCollider2D;
if (!this.sfxAudio || !this.collider) return;

// CRITICAL: enable collision events before registering listener
this.collider.emitCollisionEvent = true;

this.collisionCallback = (event: APJS.IEvent) => {
// Play SFX on each collision
this.sfxAudio.stop();
this.sfxAudio.loopCount = 1;
this.sfxAudio.play();
};

// Use object emitter on the COLLIDER (not global emitter)
const emitter = APJS.EventManager.getObjectEmitter(this.collider);
emitter.on(APJS.CollisionEvent2D.Enter, this.collisionCallback, this);
this.initialized = true;
}

onDestroy(): void {
if (this.collider && this.collisionCallback) {
const emitter = APJS.EventManager.getObjectEmitter(this.collider);
emitter.off(APJS.CollisionEvent2D.Enter, this.collisionCallback, this);
}
}
}
Copyright © 2026 TikTok. All rights reserved.
About TikTokHelp CenterCareersContactLegalTerms of ServicePrivacy PolicyCookies