Collider asset type, CollisionSystem and collision nodes
- Asset type 'collider' (box/circle) placed as child of a body object - 'Add collider' shortcut (hierarchy context menu + inspector) - CollisionSystem with enter/stay/exit pairs, sibling colliders excluded - Nodes: On collision enter/stay/exit, Is touching - Green outline in edit mode, hidden in play Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
26d5edc496
commit
0a59513b74
21 files changed
+525
-16
No files matched your search
@@ -51,6 +51,11 @@ export interface NodeContext {
|
||||
dt: number;
|
||||
findByName(name: string): EntityHandle | null;
|
||||
isKeyDown(key: string): boolean;
|
||||
/**
|
||||
* Whether any collider of `a` overlaps any collider of `b` right now. A collider entity
|
||||
* stands for itself; any other entity stands for its direct collider children.
|
||||
*/
|
||||
isTouching(a: EntityHandle, b: EntityHandle): boolean;
|
||||
log(message: string): void;
|
||||
destroy(target: EntityHandle): void;
|
||||
stop(): void;
|
||||
|
||||
@@ -32,6 +32,12 @@ registerNode({
|
||||
outputs: [exec()],
|
||||
params: [{ key: 'interval', label: 'Interval (s)', kind: 'number', default: 1, min: 0.01, step: 0.1 }],
|
||||
});
|
||||
// Collision events reach the behavior whose owner is the collider's body (the collider's
|
||||
// parent, or the collider itself when it is top-level). `other` is the other body.
|
||||
const collisionOutputs = (): PortDef[] => [exec(), obj('other'), obj('otherCollider', 'other collider'), obj('collider')];
|
||||
registerNode({ type: 'OnCollisionEnter', label: 'On collision enter', category: 'event', description: 'Runs once when a collider of the owner starts overlapping another collider.', inputs: [], outputs: collisionOutputs(), params: [] });
|
||||
registerNode({ type: 'OnCollisionStay', label: 'On collision stay', category: 'event', description: 'Runs every frame while a collider of the owner overlaps another collider.', inputs: [], outputs: collisionOutputs(), params: [] });
|
||||
registerNode({ type: 'OnCollisionExit', label: 'On collision exit', category: 'event', description: 'Runs once when a collider of the owner stops overlapping another collider.', inputs: [], outputs: collisionOutputs(), params: [] });
|
||||
|
||||
// --- flow ---------------------------------------------------------------------------------
|
||||
|
||||
@@ -266,6 +272,20 @@ registerNode({ type: 'And', label: 'And', category: 'data', description: 'Both t
|
||||
registerNode({ type: 'Or', label: 'Or', category: 'data', description: 'Either true.', inputs: [bool('a'), bool('b')], outputs: [bool('result')], params: [], run: (_c, i) => ({ outputs: { result: asBoolean(i.a) || asBoolean(i.b) } }) });
|
||||
registerNode({ type: 'Not', label: 'Not', category: 'data', description: 'Inverts a boolean.', inputs: [bool('value')], outputs: [bool('result')], params: [], run: (_c, i) => ({ outputs: { result: !asBoolean(i.value) } }) });
|
||||
registerNode({ type: 'KeyIsDown', label: 'Key is down', category: 'data', description: 'Whether a key is currently held.', inputs: [], outputs: [bool('down')], params: [keyParam], run: (ctx, _i, p) => ({ outputs: { down: ctx.isKeyDown(String(p.key ?? '')) } }) });
|
||||
registerNode({
|
||||
type: 'IsTouching',
|
||||
label: 'Is touching',
|
||||
category: 'data',
|
||||
description: 'Whether the colliders of two objects overlap right now (an object stands for its collider children; a collider for itself).',
|
||||
inputs: [obj('a'), obj('b')],
|
||||
outputs: [bool('result')],
|
||||
params: [],
|
||||
run: (ctx, i) => {
|
||||
const a = asEntity(i.a);
|
||||
const b = asEntity(i.b);
|
||||
return { outputs: { result: Boolean(a && b && ctx.isTouching(a, b)) } };
|
||||
},
|
||||
});
|
||||
|
||||
// --- actions --------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in new issue
Block a user