Skip to content

[Feature] Deliver physics backend events to subscribers and USC scripts - #1139

Merged
untoldengine merged 1 commit into
untoldengine:developfrom
miolabs:feature/physics_events-upstream
Aug 12, 2026
Merged

[Feature] Deliver physics backend events to subscribers and USC scripts#1139
untoldengine merged 1 commit into
untoldengine:developfrom
miolabs:feature/physics_events-upstream

Conversation

@miogds

@miogds miogds commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

PR C of the narrowed phase-1 plan from discussion #1116 (follows #1123 and #1129): event delivery. Backends already buffer contact/trigger/activation events internally and hand them to the coordinator's sink on the frame thread after each fixed substep (drainEvents, from PR A's threading contract) — this PR makes that drain go somewhere. With no external backend installed nothing is ever dispatched: the built-in integrator has no collision detection, so the whole path stays dormant and runtime behavior is unchanged.

  • Sources/UntoldEngine/Physics/PhysicsEvents.swift — subscription hub in the FrameEvents style: onContact/onTrigger/onActivation return the existing EventSubscription token; handlers run on the frame thread during the post-step drain, in backend delivery order; subscriptions can be created/cancelled from any thread (snapshot-under-lock dispatch, same reentrancy semantics as FrameEventDispatcher). droppedEventCount surfaces backend fixed-capacity buffer overflow as a running counter — never an allocation or error mid-step.
  • PhysicsEventDispatchSink replaces the coordinator's inert placeholder sink and also wires USC: contactBegan fires the previously never-fired OnCollision on both entities, plus the builder's tagged form OnCollision:<name> when the other entity has an explicit name; triggerEntered/triggerExited fire OnTriggerEnter/OnTriggerExit the same way (both names already appear in USCInstruction's event-handler documentation). Firing respects gameMode, via the existing USCSystem.triggerEvent path — no USC internals changed.
  • 9 new tests with an event-emitting mock backend: subscription dispatch and cancellation, dormancy without a backend, drop-counter accumulation across substeps, USC OnCollision (untagged, tagged-by-name, and phase-filtered — persisted/ended must not re-fire), trigger enter/exit scripts, and gameMode gating.

The only files touched are in Physics/ plus the two physics test files. Follow-up per the plan: PR D (raycast facade) completes phase 1.

Test plan

  • swift test --filter PhysicsEventsTests — 9/9 pass
  • PhysicsCoordinatorTests + PhysicsBackendRegistryTests — 30/30 pass
  • Full UntoldEngineTests module: 1093 tests, no new failures (only the known env-dependent ExternalRenderExtensionPackageTests)
  • make lint with pinned SwiftFormat 0.60.1 — clean

PR C of the physics plugin readiness plan (discussion untoldengine#1116):

- PhysicsEvents subscription hub in the FrameEvents style: onContact/
  onTrigger/onActivation return EventSubscription tokens; handlers run
  on the frame thread during the coordinator's post-step drain, in
  backend delivery order. droppedEventCount surfaces backend buffer
  overflow as a counter, never an allocation mid-step.
- PhysicsEventDispatchSink replaces the coordinator's inert sink: fans
  events out to subscribers and fires USC script events — contactBegan
  fires the previously never-fired OnCollision (plus OnCollision:<name>
  when the other entity is named, matching the builder's tag form), and
  trigger enter/exit fire OnTriggerEnter/OnTriggerExit the same way.
- With no external backend installed nothing is dispatched — the hub is
  dormant and runtime behavior is unchanged.

9 new tests with an event-emitting mock backend: subscription dispatch
and cancellation, dormancy without a backend, drop-counter accumulation,
USC OnCollision (untagged, tagged, phase-filtered), trigger enter/exit,
and gameMode gating.
@untoldengine
untoldengine merged commit 75917cf into untoldengine:develop Aug 12, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants