Skip to main content

CircleCollider2D

A circular 2D collider.

TypeNameInterface Description
VariablesfitImage: boolean

Function: Gets or sets whether this collider should automatically fit the attached image. When enabled, the runtime can use the image size as input for circle sizing behavior.

Variablesradius: number

Function: Gets or sets the authored radius of the 2D circle collider. Larger values produce a larger circular collision region.

Functionsconstructor()

Examples

constructor()

let obj = new APJS.CircleCollider2D();

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 — Track score via 2D collision events: enable emitCollisionEvent on CircleCollider2D, listen to CollisionEvent2D.Enter via getObjectEmitter, toggle RigidBody2D.st…

@component()
export class CollisionScoreTracker extends APJS.BasicScriptComponent {
@serializeProperty
private playerObject: APJS.SceneObject;
@serializeProperty
private scoreTextObject: APJS.SceneObject;

private rigidBody: APJS.RigidBody2D;
private collider: APJS.CircleCollider2D;
private scoreText: APJS.Text;
private score: number = 0;
private released: boolean = false;

onStart(): void {
this.rigidBody = this.playerObject.getComponent("RigidBody2D") as APJS.RigidBody2D;
this.collider = this.playerObject.getComponent("CircleCollider2D") as APJS.CircleCollider2D;
this.scoreText = this.scoreTextObject.getComponent("Text") as APJS.Text;
if (this.rigidBody) this.rigidBody.static = true;
if (this.collider) {
this.collider.emitCollisionEvent = true;
const emitter = APJS.EventManager.getObjectEmitter(this.collider);
emitter.on(APJS.CollisionEvent2D.Enter, this.onCollision);
}
APJS.EventManager.getGlobalEmitter().on(APJS.EventType.Touch, this.onTouch);
APJS.EventManager.getGlobalEmitter().on(APJS.EventType.RecordStart, this.onRecordStart);
}

private onTouch = (event: APJS.IEvent) => {
const touch = event.args[0] as APJS.TouchData;
if (touch.phase === APJS.TouchPhase.Began && !this.released) {
this.released = true;
if (this.rigidBody) this.rigidBody.static = false;
}
};

private onCollision = (event: APJS.IEvent) => {
const infos = event.args[0] as APJS.CollisionInfo2D[];
for (const info of infos) {
const other = info.otherObject as APJS.SceneObject;
if (other) {
this.score++;
if (this.scoreText) this.scoreText.text = `Score: ${this.score}`;
}
}
};

private onRecordStart = () => {
this.score = 0;
this.released = false;
if (this.rigidBody) this.rigidBody.static = true;
if (this.scoreText) this.scoreText.text = "Score: 0";
};

onDestroy(): void {
APJS.EventManager.getGlobalEmitter().off(APJS.EventType.Touch, this.onTouch);
APJS.EventManager.getGlobalEmitter().off(APJS.EventType.RecordStart, this.onRecordStart);
if (this.collider) {
this.collider.emitCollisionEvent = false;
const emitter = APJS.EventManager.getObjectEmitter(this.collider);
emitter.off(APJS.CollisionEvent2D.Enter, this.onCollision);
}
}
}
Copyright © 2026 TikTok. All rights reserved.
About TikTokHelp CenterCareersContactLegalTerms of ServicePrivacy PolicyCookies