Ammo.js Error (Cannot read properties of undefined) with ES6 Modules Loaded via Angular

Hi everyone,

We’re testing a PlayCanvas project using the new ES6 module (.mjs) export feature.

Our setup involves embedding the PlayCanvas build within an Angular application. We download the build and load it manually from an Angular service.

To handle the module structure, we’re dynamically importing a customized index.mjs file like this:

JavaScriptconst path = /js/index.mjs; await import(/* @vite-ignore */ path);

Our custom index.mjs is based on the original, with modifications only for canvas creation and handling resize/reflow logic to integrate with Angular.

The problem is that we frequently encounter an intermittent error when Ammo.js initializes:

TypeError: Cannot read properties of undefined (reading 'apply')
    at b._emscripten_bind_btDefaultCollisionConfiguration_btDefaultCollisionConfiguration_0 (ammo.wasm.js:62:238)
    at new NA (ammo.wasm.js:487:68)
    at RigidBodyComponentSystem.onLibraryLoaded (playcanvas-stable.min.mjs:55705:43)
    at AppBase.onLibrariesLoaded (playcanvas-stable.min.mjs:38977:36)
    at AppBase._loadLibraries (playcanvas-stable.min.mjs:38724:18)
    at AppBase._parseApplicationProperties (playcanvas-stable.min.mjs:38700:14)
    at Object.callback (playcanvas-stable.min.mjs:38603:18)
    at Http._onSuccess (playcanvas-stable.min.mjs:16566:21)
    at Http._onReadyStateChange (playcanvas-stable.min.mjs:16537:30)
    at xhr.onreadystatechange (playcanvas-stable.min.mjs:16473:18)

This happens within ammo.wasm.js. We’re unsure if the issue lies in our manual loading process, the interaction with Angular/Vite, our index.mjs modifications, or something else related to Ammo initialization in this context.

Could anyone offer suggestions on how to debug this or point us toward potential causes?

Thanks for your help!

1 Like

I would start with using a debug build of PlayCanvas, which you are not using (seeing the logs using playcanvas-stable.min.mjs). Replace it with a debug build, so you would have more asserts on the JS side.

You could then place a breakpoint at the line

at RigidBodyComponentSystem.onLibraryLoaded (playcanvas-stable.min.mjs:55705:43)

and check if global Ammo variable is initialized properly. Looks like you are not, since you are probably stuck at this line, which is the first use of Ammo instance:

Make sure Ammo Wasm and JS glue files are served by your server and loaded correctly (check network tab of Chrome dev-tools or any other errors/warnings in the console).

1 Like

I found a solution by adding a short pause inside the main function. I inserted a 500-millisecond setTimeout delay just after the modules finish loading (await loadModules(...)) and right before the configure() function runs.

sync function main() {
    try {
        const device = await createLocalGraphicsDevice();
        if (initApp(device)) {
            await loadModules(PRELOAD_MODULES, ASSET_PREFIX)
            await new Promise(resolve => setTimeout(resolve, 500));
            configure();
        }
    } catch (e) {
        console.error('Device creation error:', e);
    }
}

Adding this brief wait seems to fix the issue, and my tests show it works correctly on different platforms.