Skip to content

Add AppOptions.physicsWorld for explicit physics backend selection - #9266

Merged
willeastcott merged 3 commits into
mainfrom
physics-backend-selection
Sep 1, 2026
Merged

Add AppOptions.physicsWorld for explicit physics backend selection#9266
willeastcott merged 3 commits into
mainfrom
physics-backend-selection

Conversation

@willeastcott

Copy link
Copy Markdown
Contributor

Description

Follow-up to #9043, which decoupled physics into a backend abstraction but deferred "a public selection API (e.g. via AppOptions) until a second real backend lands". This PR lands that API now, proven with the existing backends, so that a future backend (e.g. Jolt) becomes purely additive — a new leaf module plus one line of user code, with zero framework changes.

const options = new AppOptions();
options.physicsWorld = new AmmoPhysicsWorld(); // or new NullPhysicsWorld()

What changed

  • AppOptions.physicsWorld (instance-valued, mirroring soundManager): AppBase.init() installs it into the RigidBodyComponentSystem, which registers itself as the world's contact listener — users never touch listener plumbing. Injection happens before onLibrariesLoaded, so Ammo auto-detection is cleanly skipped when a world is supplied.
  • Minimal public @alpha surface: PhysicsWorld, AmmoPhysicsWorld and NullPhysicsWorld are exported; the documented API is just the constructors, PhysicsWorld#nativeWorld (the native escape hatch) and RigidBodyComponentSystem#physicsWorld. The backend contract methods (createBody, createShape, joints, raycasts, descriptor typedefs) stay @ignored — implementer documentation lives in the source and the .d.ts retains full types for subclassing, but the docs site and API report only advertise what applications actually call.
  • Parameterless constructors: the contactListener constructor option was redundant once the system wires the listener on install, so it's removed. AmmoPhysicsWorld now Debug.asserts with a clear message if constructed before the Ammo library has loaded.
  • Cleanups: removed the dead off('update') branch in onLibraryLoaded, declared the Ammo world's constructor-assigned internals as tagged class fields so they no longer leak into the generated API reference, and made the RigidBodyComponentSystem class doc backend-neutral.
  • Tests: new test/framework/physics/app-options-physics-world.test.mjs — the first tests to construct AppBase + AppOptions directly — covering installation during init, contact listener wiring, auto-detect skip, component body creation through the injected world, the single-install assert and world ownership on destroy.

Notes for reviewers

  • No behavior change for existing applications: the Ammo auto-detect path (onLibraryLoaded) is untouched and remains the default for the Editor and engine-only apps that load Ammo without setting the option. It becomes the deprecation target for a future major, once explicit injection is the norm.
  • The API report will flag the new @alpha surface — that's the intended minimal set.
  • Generated docs pages were verified to show only the constructor and nativeWorld for each world class.

Checklist

  • I have read the contributing guidelines
  • My code follows the project's coding standards
  • This PR focuses on a single change

🤖 Generated with Claude Code

Lands the public backend-selection API deferred in #9043. A physics
backend can now be supplied at application construction:

    const options = new AppOptions();
    options.physicsWorld = new AmmoPhysicsWorld();

- AppBase.init installs the injected world into the rigid body system,
  which registers itself as the world's contact listener
- PhysicsWorld, AmmoPhysicsWorld and NullPhysicsWorld are exported as
  @Alpha API; the backend contract methods remain internal (@ignore)
- Backend constructors are now parameterless (the redundant
  contactListener option is removed)
- Ammo auto-detection is unchanged and skipped when a world is injected
- Adds tests covering injection, listener wiring, auto-detect skip,
  component body creation and world ownership

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Public API report

This PR changes the public API surface (+11 / −0), per the docs' rules (@ignore / @Private / undocumented are excluded).

Show API diff
+AmmoPhysicsWorld.constructor()
+AmmoPhysicsWorld.nativeWorld: any
+AppOptions.physicsWorld: PhysicsWorld
+NullPhysicsWorld.constructor()
+NullPhysicsWorld.nativeWorld: any
+PhysicsWorld.constructor()
+PhysicsWorld.nativeWorld: any
+RigidBodyComponentSystem.get physicsWorld(): PhysicsWorld | null
+class AmmoPhysicsWorld extends PhysicsWorld
+class NullPhysicsWorld extends PhysicsWorld
+class PhysicsWorld

Informational only — this never fails the build.

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown

Build size report

This PR changes the size of the minified bundles.

Bundle Minified Gzip Brotli
playcanvas.min.js 2391.8 KB (+0.4 KB, +0.02%) 615.1 KB (+0.1 KB, +0.02%) 477.1 KB (−0.1 KB, −0.03%)
playcanvas.min.mjs 2389.1 KB (+0.4 KB, +0.02%) 613.8 KB (+0.1 KB, +0.02%) 476.8 KB (+0.1 KB, +0.01%)

@willeastcott willeastcott self-assigned this Aug 30, 2026
@willeastcott willeastcott added enhancement Request for a new feature area: physics Physics related issue labels Aug 30, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@willeastcott

willeastcott commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

@LeXXik @mvaligursky, this is the groundwork needed to offer alternative physics back-ends. It's treeshake-friendly. Let me know if you have any concerns.

@LeXXik

LeXXik commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Looks good. I noticed we don't have an ability to pause the backend (e.g. game menu opened - world freezes). Something like app.physics.paused = true, so that step is not called (or can be called manually). Can be in another PR.

Edit: extracted feature request to #9272

Comment thread src/index.js Outdated

@mvaligursky mvaligursky left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look great.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@willeastcott
willeastcott merged commit 4db926f into main Sep 1, 2026
10 checks passed
@willeastcott
willeastcott deleted the physics-backend-selection branch September 1, 2026 10:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: physics Physics related issue enhancement Request for a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants