[ALPHA] WebWorker + WASM physics with PlayCanvas


Today I am glad to show you my little experiment with physics and PlayCanvas.
As you might know, PlayCanvas uses bullet’s port Ammo.js for physics calculation.

The problem is, it calculates in main thread with graphics render.
So it means that every frame you have to wait until physics and graphics is done.

When your scene is complex it can causes glitches if your computes isn’t powerful enough.
But I am working on solution for this problem. And it’s name is WebWorker.

What is it?
WebWorker allows us to calculate physics in a separated thread. So you don’t have to wait until physics is done, only graphics render.

How can it help your game?
When your game has a lot of complex meshes, you need more time to render it. With WebWorker you have more time, because you don’t need to wait for physics every frame!

When your game has a lot of rigid bodies, your scene doesn’t lock to wait until it’s calculated. Yes, it lags, but your game is not!

Which advantages does it give?
You can have either more complex meshes and rigid bodies with stable FPS or more difficult physics calculations the with the same framerate.

Let’s compare

How can I see the difference?
There is a scene with 1000 cubes.

http://mikefinch.ru/hosted/index.php - WASM Ammo.js + WebWorker
http://mikefinch.ru/hosted/index.php?native - Native Ammo.js

(Works only in major browsers such a Google Chrome)

You can rotate your camera to see that your render is not locking because of difficult physics calculations (unless you have a really low performance)

Separated physics is a good approach for web game development.

Will PlayCanvas implement it?
I don’t know. Probably one day. I would be so happy then.
I also hope somebody from core team leave a comment here.

And I want to say personal thanks to @yaustar and @Mal_Duffin for assistance.


This would be great to have as an option! Great work Mike!

Thanks for trying this out.

Unfortunately neither link works.

I think an entire web worker version of playcanvas might help no?

No, it worthless.

You still will have only one thread.

Good evening @mikefinch, would it be possible to share the code so i can test please? I am facing loading problems due to this issue and I think it would be a solution

Well, I am afraid I’ve lost it :c

But still, since that time there are a few new technologies that can make this solution even better.
My bottleneck was transmission between playcanvas and ammo, so now we have a new way to do that.

So it makes even more sense to implement it.

@derickwelman What loading problems are you facing exactly? And how did you diagnose the problem?

I’m loading hosted GLBs from an external server and they load normally, but when i enable the collision component the application freezes for a short period

entity.addComponent('collision', {
        model: glbModel

It’ll be this for loop that is slow for you:

All those calls to addTriangle are slow. Check out this comment in the Bullet docs:


By default addTriangle won’t search for duplicate vertices, because the search is very slow for large triangle meshes.

In general it is better to directly use btTriangleIndexVertexArray instead.

But currently, btTriangleIndexVertexArray is not exposed in the ammo.idl file:

So PlayCanvas can’t use it. Maybe some work could be done to address this.

1 Like