Skip to main content

RigidBody2D

A 2D physics rigid body component.

TypeNameInterface Description
VariablesangularDamping: number

Function: Gets or sets the body's angular damping coefficient. Value typically ranges from 0 (no damping) to 1 (maximum damping). Larger values make angular velocity decay faster.

VariablesangularVelocity: number

Function: Gets or sets the rigid body's angular velocity in radians per second. Positive values indicate counter-clockwise rotation. Once the body is created, the getter returns the live simulator value. Setting this property changes the current runtime state only; use for startup configuration.

Variablesdamping: number

Function: Gets or sets the body's linear damping coefficient. Value typically ranges from 0 (no damping) to 1 (maximum damping). Larger values make linear velocity decay faster during simulation.

Variablesforce: Vector2f

Function: Gets or sets the continuous force applied to the rigid body in world space. Force is measured in Newtons and is applied continuously during physics simulation. Setting this replaces the previous continuous force value. This does NOT affect forces added via . To apply multiple forces cumulatively, use instead.

VariablesfreezeX: boolean

Function: Gets or sets whether this body is locked against horizontal movement.

VariablesfreezeY: boolean

Function: Gets or sets whether this body is locked against vertical movement.

VariablesfreezeZ: boolean

Function: Gets or sets whether this body is locked against rotation.

VariablesgravityScale: number

Function: Gets or sets the multiplier applied to global 2D gravity for this body. For example, 0 disables gravity, 1 uses normal gravity, and 2 doubles it. If is false, this value is stored but not pushed to the simulator until gravity is re-enabled.

VariablesinitialAngularVelocity: number

Function: Gets or sets the initial angular velocity of the RigidBody2D in radians per second. This value is serialized and applied when the body is first created. To read/write runtime angular velocity, use the angularVelocity property instead.

VariablesinitialVelocity: Vector2f

Function: Gets or sets the initial linear velocity of the RigidBody2D in meters per second. This value is serialized and applied when the body is first created. To read/write runtime velocity, use the velocity property instead.

Variablesmass: number

Function: Gets or sets the body's mass in kilograms. Larger mass reduces acceleration from the same applied force and affects collision response.

Variablesposition: Vector2f

Function: Gets or sets the position of the RigidBody2D in world coordinates. Position represents the center of mass of the body in 2D space. Setting this property teleports the body immediately instead of moving it through simulation. Do NOT modify ScreenTransform.anchoredPosition directly on a physics body — the engine will overwrite it on the next frame. Use this property or instead. Note: When converting from screen pixels to 2D physics world units, divide by 32.

Variablesrotation: number

Function: Gets or sets this body's authored rotation in radians. Rotation is measured counter-clockwise from the positive X-axis. Setting this property rotates the body immediately instead of moving it through simulation. Do NOT modify ScreenTransform.rotation directly on a physics body — the engine will overwrite it on the next frame. Use this property or instead.

Variablesstatic: boolean

Function: Gets or sets whether this body behaves like a non-moving physics body. When enabled, the simulator switches this body away from dynamic simulation, clears accumulated force and torque, and resets its runtime linear and angular velocity to zero. Re-enabling dynamic behavior restores the serialized initial velocity values.

Variablestorque: number

Function: Gets or sets the continuous torque applied to the rigid body in world space. Torque is measured in Newton-meters and is applied continuously during physics simulation. Setting this replaces the previous continuous torque value. This does NOT affect torques added via . To apply multiple torques cumulatively, use instead.

VariablesuseGravity: boolean

Function: Gets or sets whether gravity affects this body. When enabled, the simulator uses this body's current . When disabled, APJS pushes a native gravity scale of 0 while keeping the stored gravityScale value unchanged for later reuse.

Variablesvelocity: Vector2f

Function: Gets or sets the rigid body's world-space linear velocity in meters per second. Once the body is created, the getter returns the live simulator velocity. Setting this property changes the current runtime state only; use for startup configuration.

Functionsconstructor()

FunctionsaddForce(force: Vector2f, mode?: ForceMode2D): void

Function: Adds force to this body. Continuous modes accumulate force or acceleration until removed. Instantaneous modes apply an impulse immediately. Force modes: - Force: continuous force and mass-dependent acceleration - Acceleration: continuous acceleration independent of mass - Impulse: immediate velocity change scaled by mass - VelocityChange: immediate velocity change independent of mass

Parameters

force: - The world-space force vector in 2D physics units.

mode: - The force mode to apply. Defaults to .

FunctionsaddForceAt(force: Vector2f, position: Vector2f, isLocal?: boolean, mode?: ForceMode2D): ConstantForce2D | null

Function: Applies force at a specific point, which may also generate torque. If isLocal is true, both force and position are converted from local space to world space before the force is applied. Continuous modes return a describing the world-space force and torque contribution so it can later be removed. Instantaneous modes return null.

Parameters

force: - The force vector to apply.

position: - The application point.

isLocal: - If true, interprets inputs in local space. Defaults to false.

mode: - The force mode. Defaults to .

Returns A world-space handle for continuous modes; null for instantaneous modes.

FunctionsaddTorque(torque: number, mode?: ForceMode2D): void

Function: Adds torque to this body. Continuous modes accumulate torque or angular acceleration until removed. Instantaneous modes apply angular impulse immediately.

Parameters

torque: - The torque value in Newton-meters.

mode: - The force mode to apply. Defaults to .

Examples

position: Vector2f

rigidBody2D.position = new Vector2f(5, 3); // teleport to (5m, 3m)

constructor()

let obj = new APJS.RigidBody2D();

addForceAt(force: Vector2f, position: Vector2f, isLocal?: boolean, mode?: ForceMode2D): ConstantForce2D | null

const pushForce = new APJS.Vector2f(10, 0); // Push right
const cornerPos = new APJS.Vector2f(0.5, 0.5); // Top-right corner in local space
rigidBody2D.addForceAt(pushForce, cornerPos, true, APJS.ForceMode2D.Impulse);

Use Case

Example 1 — Tap to drop a ball/coin that bounces multiple times on a static floor — full Physics Matter resource flow (DSL: add_builtin_resource → set_resource_properties →…

@component()
export class TapToDropBouncy extends APJS.BasicScriptComponent {
private rb: APJS.RigidBody2D | null = null;
private collider: APJS.CircleCollider2D | null = null;
private touchCallback: ((event: APJS.IEvent) => void) | null = null;
private collisionCallback: ((event: APJS.IEvent) => void) | null = null;
private dropped = false;
private bounceCount = 0;

onStart(): void {
const obj = this.getSceneObject();
this.rb = obj.getComponent("RigidBody2D") as APJS.RigidBody2D;
this.collider = obj.getComponent("CircleCollider2D") as APJS.CircleCollider2D;
if (!this.rb || !this.collider) return;

// emitCollisionEvent is APJS-runtime-only — must set in onStart, not in DSL.
this.collider.emitCollisionEvent = true;

this.touchCallback = (event: APJS.IEvent) => {
const touch = event.args[0] as APJS.TouchData;
if (touch.phase === APJS.TouchPhase.Began && !this.dropped && this.rb) {
this.dropped = true;
this.rb.static = false; // gravity now applies
}
};
APJS.EventManager.getGlobalEmitter().on(APJS.EventType.Touch, this.touchCallback);

this.collisionCallback = (event: APJS.IEvent) => {
this.bounceCount++;
// Optional: stop tracking after 5 bounces, or play SFX, or update score, etc.
if (this.bounceCount === 1) console.log("[Bouncy] first impact");
};
const emitter = APJS.EventManager.getObjectEmitter(this.collider);
emitter.on(APJS.CollisionEvent2D.Enter, this.collisionCallback, this);
}

onDestroy(): void {
if (this.touchCallback) {
APJS.EventManager.getGlobalEmitter().off(APJS.EventType.Touch, this.touchCallback);
}
if (this.collisionCallback && this.collider) {
APJS.EventManager.getObjectEmitter(this.collider).off(APJS.CollisionEvent2D.Enter, this.collisionCallback, this);
}
}
}

Example 2 — On tap, apply random upward impulse to multiple 2D physics blocks using addForce with ForceMode2D.Impulse

@component()
export class TapPushBlocks extends APJS.BasicScriptComponent {
@serializeProperty
blocks: APJS.SceneObject[] = [];

private blockStartPos: APJS.Vector2f[] = [];
private blockStartGravity: boolean[] = [];
private inited = false;

private onTouch = (event: APJS.IEvent) => {
const touch = event.args[0] as APJS.TouchData;
if (touch.phase === APJS.TouchPhase.Began) {
for (const obj of this.blocks) {
const rb = obj.getComponent("RigidBody2D") as APJS.RigidBody2D;
if (rb) {
const randomX = (Math.random() - 0.5) * 200;
const upwardY = 300 + Math.random() * 200;
rb.addForce(new APJS.Vector2f(randomX, upwardY), APJS.ForceMode2D.Impulse);
}
}
}
};

// RecordStart: pool reset per Physics2D §"RecordStart Reset for 2D Physics" — iterate
// each block, apply velocity → anchoredPosition → useGravity. Cache per-block startPos
// and startGravity flag in the lazy init below. See GameState §"RecordStart / RecordEnd Lifecycle".
private onRecordStart = (_event: APJS.IEvent) => {
if (!this.inited) return;
for (let i = 0; i < this.blocks.length; i++) {
const obj = this.blocks[i];
if (!obj) continue;
const rb = obj.getComponent("RigidBody2D") as APJS.RigidBody2D;
const st = obj.getComponent("ScreenTransform") as APJS.ScreenTransform;
if (rb) rb.velocity = new APJS.Vector2f(0, 0);
if (st && this.blockStartPos[i]) {
st.anchoredPosition = new APJS.Vector2f(this.blockStartPos[i].x, this.blockStartPos[i].y);
}
if (rb && this.blockStartGravity[i] !== undefined) {
rb.useGravity = this.blockStartGravity[i];
}
}
};

onStart(): void {
APJS.EventManager.getGlobalEmitter().on(APJS.EventType.Touch, this.onTouch);
APJS.EventManager.getGlobalEmitter().on(APJS.EventType.RecordStart, this.onRecordStart);
}

onUpdate(_dt: number): void {
if (!this.inited && this.blocks.length > 0) {
for (const obj of this.blocks) {
if (!obj) continue;
const st = obj.getComponent("ScreenTransform") as APJS.ScreenTransform;
const rb = obj.getComponent("RigidBody2D") as APJS.RigidBody2D;
if (st) {
this.blockStartPos.push(new APJS.Vector2f(st.anchoredPosition.x, st.anchoredPosition.y));
} else {
this.blockStartPos.push(new APJS.Vector2f(0, 0));
}
this.blockStartGravity.push(rb ? rb.useGravity : true);
}
this.inited = true;
}
}

onDestroy(): void {
APJS.EventManager.getGlobalEmitter().off(APJS.EventType.Touch, this.onTouch);
APJS.EventManager.getGlobalEmitter().off(APJS.EventType.RecordStart, this.onRecordStart);
}
}
Copyright © 2026 TikTok. All rights reserved.
About TikTokHelp CenterCareersContactLegalTerms of ServicePrivacy PolicyCookies