BabylonJS/Babylon.js · critical

No Physics Plugin available.

Error message

No Physics Plugin available.

What it means

After confirming a v2 engine exists, PhysicsBody asks it for its plugin via physicsEngine.getPhysicsPlugin(). A null result means the engine exists but no usable plugin is registered, so the body has nothing to route simulation calls to and the constructor throws. In practice this means physics was enabled without a functioning plugin instance.

Source

Thrown at packages/dev/core/src/Physics/v2/physicsBody.ts:116

     * This code is useful for creating a physics body for a given Transform Node in a scene.
     * It checks the version of the physics engine and the physics plugin, and initializes the body accordingly.
     * It also sets the node's rotation quaternion if it is not already set. Finally, it adds the body to the physics engine.
     */
    constructor(transformNode: TransformNode, motionType: PhysicsMotionType, startsAsleep: boolean, scene: Scene) {
        if (!scene) {
            return;
        }
        const physicsEngine = scene.getPhysicsEngine() as PhysicsEngine;
        if (!physicsEngine) {
            throw new Error("No Physics Engine available.");
        }
        this._physicsEngine = physicsEngine;
        if (physicsEngine.getPluginVersion() != 2) {
            throw new Error("Plugin version is incorrect. Expected version 2.");
        }
        const physicsPlugin = physicsEngine.getPhysicsPlugin();
        if (!physicsPlugin) {
            throw new Error("No Physics Plugin available.");
        }

        this._physicsPlugin = physicsPlugin;
        if (!transformNode.rotationQuaternion) {
            transformNode.rotationQuaternion = Quaternion.FromEulerAngles(transformNode.rotation.x, transformNode.rotation.y, transformNode.rotation.z);
        }

        this.startAsleep = startsAsleep;

        // only dynamic and animated body needs sync from physics to transformNode
        this.disableSync = motionType == PhysicsMotionType.STATIC;

        // instances?
        const m = transformNode as Mesh;
        if (m.hasThinInstances) {
            this._physicsPlugin.initBodyInstances(this, motionType, m);
        } else {
            // single instance

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Await the plugin and pass it explicitly: const havok = await HavokPlugin(); scene.enablePhysics(gravity, havok);
  2. Check scene.getPhysicsEngine()?.getPhysicsPlugin() before creating bodies and fail fast if null.
  3. Re-enable physics on the scene if a previous enablePhysics call failed or omitted the plugin.

Example fix

// before
scene.enablePhysics(new Vector3(0, -9.81, 0)); // no plugin passed
new PhysicsBody(mesh, PhysicsMotionType.DYNAMIC, false, scene);
// after
const havok = await HavokPlugin();
scene.enablePhysics(new Vector3(0, -9.81, 0), havok);
new PhysicsBody(mesh, PhysicsMotionType.DYNAMIC, false, scene);
Defensive patterns

Strategy: validation

Validate before calling

const engine = scene.getPhysicsEngine() as PhysicsEngine | null;
if (!engine?.getPhysicsPlugin()) {
  throw new Error("scene has no physics plugin; call scene.enablePhysics(gravity, await HavokPlugin())");
}

Prevention

When it happens

Trigger: new PhysicsBody(...) on a scene whose engine returns null from getPhysicsPlugin() — e.g. scene.enablePhysics called without a plugin argument or with a plugin that failed to construct, checked at physicsBody.ts:116.

Common situations: Calling scene.enablePhysics(gravity) without passing the awaited HavokPlugin; passing an uninitialized plugin (HavokPlugin() promise not awaited); a scene engine constructed outside the normal enablePhysics path.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/999380ed7c3cb026. Report an issue: GitHub.