The real difficulty is integrating the current game engine with the potential wasm library - there is a careful balance to be found between not giving enough information to the wasm library (that would result in having to transfer too much data at every call, making the overhead too big) and giving it too much (that would result in having to rewrite most of the game engine in this library).
I’ve made this fairly large Pull Request a while ago: Experimental object collision and positions handling improvements by 4ian · Pull Request #1393 · 4ian/GDevelop · GitHub
It introduce a gdjs.ObjectPositionsManager
, which is a class responsible for holding the position of objects, their hitboxes, and giving operations like compute collisions, compute distances, etc…
Once we have this abstraction we could:
-
improve the efficiency of the “naive” collision/raycast/etc by storing object position in a spatial partioning structure (much like what is done in the platformer engine and in some other extensions), which is in the case of this PR a RTree. This would still be done in JavaScript as a first step.
-
Then, we could remove this JS implementation of a gdjs.ObjectPositionsManager
and instead implement it in Rust/C++/whatever compiled to wasm. This would be possible because gdjs.ObjectPositionsManager
was designed with an API that only use simple datastructures and deal with objects using their ids (so it means that for example if you want to test the collision between objects, you just have to pass their ids, which are numbers. You don’t have to serialize the full object).
Unfortunately I stopped because the performance improved in a lot of cases, but performance was also worse in some other cases for example the Asteroids example with 1500 asteroids.
This is because in some situations, it becomes more time consuming to update the gdjs.ObjectPositionsManager
every time an object moves, rather than doing what we do now (which is to not done anything, and let the collision conditions iterate on all objects).
Of course it’s something that we can expect: there will be always a situation where the performance, even with a smart spatial partitioning, will be worse than a naive approach. So I also added an implementation of gdjs.ObjectPositionsManager that would do nothing (i.e: it would just register object position, and the collision conditions would just iterate on all objects).
But even with this, some examples were still having a decreased performance, because of the “bookeeping” work of calling a function like this._runtimeScene.getObjectPositionsManager().markObjectAsDirty(this);
every time an object is moved.
If you want to take a look and help, you can fetch the branch (expect some merge conflicts to happen and to be solved). You’ll see that gdjs.ListObjectPositionsContainer
is the “naive” class doing no special bookeeping of objects. I’d like this class to be as performant as now in the case of lots of objects being moved (like the Asteroids example with 1500 asteroids). If we can find a way to do so, we would then be able to offer an option to activate spatial partitioning (gdjs.RTreeObjectPositionsContainer
: it’s a RTree)
and then even replace this last class by a wasm powered library, which would offer predictable performance
(for example, funnily enough, when I was doing benchmarks between gdjs.RTreeObjectPositionsContainer
and gdjs.ListObjectPositionsContainer
, it was important to reload the preview multiple time, to give the time to the JS engine to Just-In-Time compile the “hot” functions).