Another question regarding our multiplayer server 
I set up a local server with Colyseus, configured a room schema (battle room) so that it can hold only a single player (for debugging purposes), I created a virtual DOM with jsdom and initialized Ammo.js so physics can be simulated.
When a player joins a battle room, I start a new PC application for that player and anyone else that would join this room. Once the room is full and another player tries to join, a new room is opened and a new application is created. When player leave their room and the room is empty, the application is destroyed. So far so good.
What I now noticed is, that the first room being destroyed works fine. The second though throws errors, e.g. Cannot read properties of null (reading 'getOrigin')
. The object, that it was trying to call getOrigin
on was _ammoTransform
, which is a global variable that is created by the application for caching purposes I suppose? So once the first destroyed application has cleaned this variable, the second one can’t anymore.
There are other such variables as well, some that I found are _ammoVec1$1
_ammoQuat$1
, ammoRayStart
and ammoRayEnd
.
So my questions are, am I cleaning up the application correctly by simply calling destroy
on it, or do I have to make sure somehow that these shared variables are not cleaned up unless all applications are destroyed?
Is it even smart to run multiple applications on the same jsdom with a shared instance of Ammo? The applications don’t seem to interfere with one another when being run simultaneously.
If I have to, how would I properly encapsulate each application instance?
I hope I was clear enough, as this whole topic is still quite new to me
Thanks for any help
@mvaligursky Hi, sorry for tagging you directly, but do you or one of you colleagues know more about this, or how to best approach my problem?
Not sure what is possible here to be honest. It does not seem using Ammo with multiple applications is directly supported because of those globals. Ideally we get rid of them as globals, and make them per application instance properties.
I don’t think those variables are global. They should be module scoped?
@mvaligursky where does the engine load Ammo? Maybe it skips instantiation if Ammo is available in global scope? Then it would skip creating those variables.
@AliMoe you could try setting window.Ammo = null
before creating a new app.
I don’t think those variables are global. They should be module scoped?
Unfortunately I think they aren’t. Destroying the first of many apps works as expected, but destroying the second throws an error, as it tries to clean something up that doesn’t exist anymore.
@AliMoe you could try setting window.Ammo = null
before creating a new app.
I followed this example to create a jsdom on the server - Running the Engine in Node.js | PlayCanvas Developer Site. After creating the DOM, I have to add Ammo to the global scope, so it can be accessed by playcanvas.
...
// Initialize Ammo
global.Ammo = await new Ammo();
// Copy the PlayCanvas API to global scope (only required for 'classic' scripts)
this.jsdom.window.pc = pc;
}
Is there another way to give playcanvas access to Ammo? Should I create multiple instances of Ammo, for each app their own?
The global variables that cause these issues seem to be the ones in the Rigidbody - System and in the Rigidbody - Component. It seems like the Trigger has some of these as well, but they aren’t cleaned up anywhere, so they don’t cause any problems. Maybe this is a minor memory leak? 
I created a custom build of the engine, which counts the amount of times these cached variables would be instantiated. They are only created the first time, and they are only destroyed when the last app is destroyed. And this works great, at least at the moment.
Is this something that should be added to the engine, do you think I should open a pull request?
I ended up replacing ammo with jolt physics (massive improvement) but understandably a lot of effort. Weren’t you working on a playcanvas JOLT component @LeXXik at one point?