CollisionInfo
Information about a single 3D collision contact point.
| Type | Name | Interface Description |
|---|---|---|
| Variables | normal: Vector3f | • Function: World-space contact normal vector. |
| Variables | otherObject: SceneObject | null | • Function: The SceneObject that owns the other collider in this collision pair. This is null if APJS cannot resolve that collider back to a SceneObject. |
| Variables | point: Vector3f | • Function: World-space contact point. |
| Functions | constructor(point: Vector3f, normal: Vector3f, otherObject: SceneObject | null) |
Examples
constructor(point: Vector3f, normal: Vector3f, otherObject: SceneObject | null)
let obj = new APJS.CollisionInfo();
Use Case
Example 1 — 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);
}
}
}
Example 2 — 3D physics collision event handler. Listens on BoxCollider/SphereCollider for Enter/Stay/Exit events.
@component()
export class CollisionHandler3D extends APJS.BasicScriptComponent {
private collider: APJS.Collider;
private inited = false;
private hitCount = 0;
private onEnter = (event: APJS.IEvent) => {
this.hitCount++;
const infos = event.args[0] as APJS.CollisionInfo[];
for (const info of infos) {
if (info.otherObject) {
console.log("[Collision] Enter #" + this.hitCount + ": " + info.otherObject.name);
console.log(" point: " + info.point.x.toFixed(2) + ", " + info.point.y.toFixed(2) + ", " + info.point.z.toFixed(2));
console.log(" normal: " + info.normal.x.toFixed(2) + ", " + info.normal.y.toFixed(2) + ", " + info.normal.z.toFixed(2));
}
}
};
private onExit = (event: APJS.IEvent) => {
console.log("[Collision] Exit");
};
// RecordStart: only the script-owned hitCount accumulator needs reset; this example
// does not move any RigidBody, so no Physics3D reset block is needed. See GameState SKILL.
private onRecordStart = (_event: APJS.IEvent) => {
this.hitCount = 0;
};
onStart(): void {
APJS.EventManager.getGlobalEmitter().on(APJS.EventType.RecordStart, this.onRecordStart);
}
onUpdate(dt: number): void {
if (!this.inited) {
const obj = this.getSceneObject();
if (!obj) return;
// Try BoxCollider first, then SphereCollider
this.collider = obj.getComponent("BoxCollider") as APJS.BoxCollider;
if (!this.collider) {
this.collider = obj.getComponent("SphereCollider") as APJS.SphereCollider;
}
if (!this.collider) return;
this.inited = true;
this.collider.emitCollisionEvent = true;
// CRITICAL: pass collider, NOT sceneObject
const emitter = APJS.EventManager.getObjectEmitter(this.collider);
emitter.on(APJS.CollisionEvent.Enter, this.onEnter, this);
emitter.on(APJS.CollisionEvent.Exit, this.onExit, this);
}
}
onDestroy(): void {
if (this.collider) {
const emitter = APJS.EventManager.getObjectEmitter(this.collider);
emitter.off(APJS.CollisionEvent.Enter, this.onEnter, this);
emitter.off(APJS.CollisionEvent.Exit, this.onExit, this);
}
APJS.EventManager.getGlobalEmitter().off(APJS.EventType.RecordStart, this.onRecordStart);
}
}