Skip to main content

RigidBody

A 3D physics rigid body component.

TypeNameInterface Description
VariablesangularDamping: number

Function: Gets or sets the angular damping coefficient that reduces angular velocity over time. Value typically ranges from 0 (no damping) to 1 (maximum damping). Higher values cause the body to stop rotating faster.

VariablesangularVelocity: Vector3f

Function: World-space angular velocity in radians per second. The vector points along the rotation axis, the getter returns the live simulator value, and writing overrides the current physics-computed angular velocity immediately. For gradual changes, use instead.

Variablesdamping: number

Function: Gets or sets the linear damping coefficient that reduces linear velocity over time. Value typically ranges from 0 (no damping) to 1 (maximum damping). Higher values cause the body to slow down faster.

VariableseulerAngles: Vector3f

Function: Current world-space rotation of the rigid body as Euler angles in radians (rotation order XYZ). The getter reflects the live orientation from the physics engine. Writing teleports the body immediately. For smooth rotation, use . Do NOT modify Transform.eulerAngles directly — it will be overwritten. Prefer over this property to avoid gimbal lock.

Variablesforce: Vector3f

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 movement along the X-axis is frozen. When frozen, the rigid body cannot move along the X-axis but can still rotate freely. Constraint is applied during the next physics simulation step.

VariablesfreezeY: boolean

Function: Gets or sets whether movement along the Y-axis is frozen. When frozen, the rigid body cannot move along the Y-axis but can still rotate freely. Constraint is applied during the next physics simulation step.

VariablesfreezeZ: boolean

Function: Gets or sets whether movement along the Z-axis is frozen. When frozen, the rigid body cannot move along the Z-axis but can still rotate freely. Constraint is applied during the next physics simulation step.

VariablesinertiaTensor: Vector3f

Function: Gets or sets the diagonal inertia tensor of the rigid body. These values describe resistance to angular acceleration around the body's principal axes. They are usually computed automatically from mass and collider shape, but can be overridden for custom behavior.

Variablesmass: number

Function: Gets or sets the mass of the rigid body in kilograms. Mass must be positive and greater than zero. Changing mass during simulation affects the body's inertia and response to forces.

VariablesphysicsAnimation: boolean

Function: Blend animation with physics. When enabled, a hidden kinematic "shadow body" follows the animation, and the real physics rigid body is pulled toward it via spring-like joints. - physicsAnimation = false: pure physics (forces/gravity drive motion) - physicsAnimation = true, rate = 0: pure animation (body exactly follows animation) - physicsAnimation = true, rate = 0.5: blend (physics and animation mix) - physicsAnimation = true, rate = 1.0: mostly physics, loosely follows animation Requires the SceneObject or an ancestor to have an Animator component. Performance: Creates two additional constraints per body.

VariablesphysicsAnimationRate: number

Function: Controls the blend between animation and physics when is enabled. Range [0, 1]: - 0 = pure animation (rigid body rigidly follows the animated transform) - 1 = mostly physics (animation only loosely guides, gravity/forces dominate) Internally maps to joint compliance: low rate = stiff springs = tight animation tracking.

Variablesposition: Vector3f

Function: World-space position of the rigid body (meters). Reads from the physics engine; writing teleports the body immediately, bypassing velocity/force simulation. Do NOT modify Transform.position directly on a physics-controlled object — the physics engine will overwrite it on the next frame. Use this property or instead to move the body.

Variablesrotation: Quaternionf

Function: Current world-space rotation of the rigid body, returned as a quaternion. Once the body is created, the getter reflects the live orientation from the physics engine. Writing teleports the body's rotation immediately, bypassing torque and angular-velocity simulation. Do NOT modify Transform.rotation directly on a physics-controlled object — the physics engine will overwrite it on the next frame. Use this property, , or instead.

Variablesstatic: boolean

Function: Gets or sets whether the rigid body behaves as an immovable kinematic body. When enabled, the PBD simulator stops treating this body as dynamically simulated. Use this for environment geometry or authored placement that should not respond to forces.

Variablestorque: Vector3f

Function: Gets or sets the continuous torque (the external force that causes a rigid body to rotate) 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 scene gravity contributes to this body's continuous external force. When enabled, APJS adds Physics3D.gravity * mass to the body's accumulated external force. Disabling gravity removes that contribution without changing any other forces already applied to the body.

Variablesvelocity: Vector3f

Function: World-space linear velocity in meters per second (m/s). The getter returns the live simulator value, and writing overrides the current physics-computed velocity immediately. For gradual changes, use instead.

Functionsconstructor()

FunctionsaddForce(force: Vector3f, mode?: ForceMode3D): void

Function: Adds force at the rigid body's center of mass. Force modes: - Force: adds continuous force and scales with mass - Acceleration: adds continuous acceleration independent of mass - Impulse: applies an immediate impulse and changes velocity instantly - VelocityChange: applies an immediate velocity change independent of mass

Parameters

force: - The world-space force vector to apply.

mode: - The type of force application. Defaults to .

FunctionsaddForceAt(force: Vector3f, position: Vector3f, isLocal?: boolean, mode?: ForceMode3D): ConstantForce3D | null

Function: Applies a force at a specific point, which may also generate torque. If isLocal is true, both force and position are interpreted in the object's local space and converted to world space before applying the force.

Parameters

force: - The force vector to apply.

position: - The application point.

isLocal: - If true, force and position are in local space. Defaults to false.

mode: - The mode of the force (Force, Impulse, etc.). Defaults to .

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

FunctionsaddTorque(torque: Vector3f, mode?: ForceMode3D): void

Function: Adds torque at the rigid body's center of mass. Force modes: - Force: adds continuous torque and scales with mass - Acceleration: adds continuous angular acceleration independent of mass - Impulse: applies an immediate angular impulse - VelocityChange: applies an immediate angular velocity change independent of mass

Parameters

torque: - The world-space torque vector to apply.

mode: - The type of torque application. Defaults to .

Examples

position: Vector3f

// Teleport a physics body to (0, 5, 0)
rigidBody.position = new APJS.Vector3f(0, 5, 0);
// For smooth movement, use forces:
rigidBody.addForce(new APJS.Vector3f(0, 10, 0), APJS.ForceMode3D.Impulse);

rotation: Quaternionf

// Teleport rotation (90 degrees around Y axis, 1.57 radians)
rigidBody.rotation = APJS.Quaternionf.makeFromEulerAngles(new APJS.Vector3f(0, 1.57, 0));
// For smooth rotation, use torque:
rigidBody.addTorque(new APJS.Vector3f(0, 10, 0), APJS.ForceMode3D.Impulse);

constructor()

let obj = new APJS.RigidBody();

addForce(force: Vector3f, mode?: ForceMode3D): void

const explosionForce = new APJS.Vector3f(0, 100, 0);
rigidBody.addForce(explosionForce, APJS.ForceMode3D.Impulse);

addForceAt(force: Vector3f, position: Vector3f, isLocal?: boolean, mode?: ForceMode3D): ConstantForce3D | null

push something at a specific point
// Apply a push at the edge of the object to make it swing
const pushForce = new APJS.Vector3f(0, 0, 10); // Push forward
const pushPoint = new APJS.Vector3f(1, 0, 0); // Right edge
rigidBody.addForceAt(pushForce, pushPoint, false, APJS.ForceMode3D.Impulse);

addTorque(torque: Vector3f, mode?: ForceMode3D): void

const explosionTorque = new APJS.Vector3f(0, 100, 0);
rigidBody.addTorque(explosionTorque, APJS.ForceMode3D.Impulse);

Use Case

Example 1 — 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);
}
}

Example 2 — 3D physics: tap anywhere to apply an upward impulse to a RigidBody object.

@component()
export class TapImpulse extends APJS.BasicScriptComponent {
@serializeProperty
impulseStrength: number = 50;

private rb: APJS.RigidBody;
private inited = false;
private startPos!: APJS.Vector3f;
private startRot!: APJS.Quaternionf;
private startGravityOn = true;

private onTouch = (event: APJS.IEvent) => {
const touch = event.args[0] as APJS.TouchData;
if (touch.phase === APJS.TouchPhase.Began && this.rb) {
// Impulse: one-shot force, object falls back under gravity
this.rb.addForce(
new APJS.Vector3f(0, this.impulseStrength, 0),
APJS.ForceMode3D.Impulse
);
}
};

// RecordStart: reset per Physics3D §"RecordStart Reset for 3D Physics" — full 6-step
// single-body block (velocity → angularVelocity → position → rotation → useGravity →
// accumulators). See GameState §"RecordStart / RecordEnd Lifecycle".
private onRecordStart = (_event: APJS.IEvent) => {
if (!this.inited) return;
this.rb.velocity = new APJS.Vector3f(0, 0, 0);
this.rb.angularVelocity = new APJS.Vector3f(0, 0, 0);
this.rb.position = new APJS.Vector3f(this.startPos.x, this.startPos.y, this.startPos.z);
this.rb.rotation = this.startRot;
this.rb.useGravity = this.startGravityOn;
};

onUpdate(dt: number): void {
if (!this.inited) {
const obj = this.getSceneObject();
if (!obj) return;
this.rb = obj.getComponent("RigidBody") as APJS.RigidBody;
if (!this.rb) return;
this.startPos = new APJS.Vector3f(this.rb.position.x, this.rb.position.y, this.rb.position.z);
this.startRot = this.rb.rotation;
this.startGravityOn = this.rb.useGravity;
this.inited = true;

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

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