Test an experimental version with optimizations in collision handling

I’ve been working on some internal changes that adds the usage of an optimised data structure to handle collisions between large amounts of objects, and also improving the conditions testing the distance between objects, raycast and a few others.

This is internal to the game engine and should not affect your game behavior. In theory, this optimised data structure allow for much greater performance in scenarios where you have lots of objects (for example, checking collision between the player and walls in a large map).

This being said, these changes are quite large and I want to minimize the risk of regression (bug in a condition). I want also to verify if there are games for which this optimisation is counter productive, making the game slower.

If you have some time, you can help me by installing the testing version I’ve linked at the end of this post. This is just for testing! Make a backup of your game before and be sure to use this version only to give a try to your game. Get back to the latest “official” version (beta 88 right now) to continue working on your game.

Find the links here:

If you can answer to this post with either a confirmation that:

  • your game is working as usual
  • you have seen some minor changes (please explain what they are - double check if this is the case when running with the official version)
  • or if your game is broken. In this case, it would be super useful to either send me the game (+ a description of what is not working) or (even better) an example game that is showing the issue :slight_smile:

Thanks :smiley:

10 Likes

So nice to see this changes :slight_smile:

I would try it but don’t have any made project at moment except for a quiz game like millionare. Would it be useful if i test it in that quiz ?

Thanks for all your hard work 4ian !

1 Like

I’ve been using the Asteroids example to test and I am getting worst performance.

With 1500 large asteroids spawned initially I’m getting stable 30-35 FPS with the current beta.
With this new experimental version, I’m getting only 12-15 FPS.

I’ve been trying only in preview on my Windows 10 desktop.

Here is the modified project, I set it to spawn 1500 asteroids and the player won’t be destroyed on collision but do check collision with all 1500 asteroids and you can destroy them all.

Regarding other problems, bugs, I haven’t noticed anything new.

Thanks @ddabrahim I’ll take a look :slight_smile:
Sometimes you can get worse performance at first during the time the JS engine is just-in-time compiling the new game engine code, but after a few seconds (or after relaunching the preview) it should settle down.

I’ll give a look anyway, if the risk of performance loss is too high I’ll make an option to disable the usage of the spatial data structure (or even make it opt in)

I’ve been waiting few minutes (guess it should be enough) but noticed no improvement. With the experimental version the FPS is not going above 15 :frowning:

Should be more than enough yeah, in the case of this game the update to the positions of the asteroids in the spatial data structure is too resource consuming compared to the benefits when testing collision. Let me see what I can do.

What sort of benefits are these? I’m not sure what to look for exactly. I did a more simple test for collision, created 10,000 objects and checking collision with each and I was getting about the same FPS (30-35) with both version of GD in preview on Windows 10. I noticed no improvement there. :thinking:

This is the project I tried:

On my Windows 10 laptop with integrated Intel graphics and Pentium CPU I get slightly better performance (3-4 FPS more) with the experimental version compared to the current beta. Maybe more people should try this example and see what the result is on different configurations…

Also tried distance check with 10,000 objects and I get worse performance in the experimental version.
I get 32-35 FPS in the current beta and only 23-25 FPS in the experimental version in preview on Windows 10

Here is the project I tried, it is the same as the collision one but checking distance:

For collision, to notice an improvement I think you have to add multiple players objects.

Try this:

I’m getting 50-60 FPS on my mac with the new version, ~30 with the old version.

For this, reverse the condition:

Should be a bit better because the distance will query the “Obstacle” using the spatial data structure. When puttin Obstacle first, the condition is iterating on all Obstacle, and for each query the Player. There is only one so no performance improvement (even worse because of the overhead).

Though this seems to indicate that the condition should explicitly tell the object that is in smallest “quantity” must be first. Or I can see if I can do this automatically in the engine.

1 Like

As another example, if in the one with distance checking, you put Player first in the condition as I shown and put ~9 players, I’m getting 55-60 fps with the new version and 30 with the old.

Also be sure to lower the minimum FPS to 1 if your reaching the number of 20fps. By default if the game is going slower than 20fps, the time of the game is “slowed down”, so your FPS counter will keep showing 20.

This being said, it’s true that the improvement in the case where you have “1 object versus 10000” is not big. The spatial data structure seems to shine when you have “a lot of objects versus a lot of objects”, as shown by the measure I got when duplicating the Player objects.
Might be worth taking another look to see if I can automate the ideal ordering of the objects in the condition…

Weird, the experimental version is still a few frames worse on my end, getting the same 32-35 with current beta and 29-30 with the experimental :face_with_raised_eyebrow:

Indeed it is much better, I’m getting 20 FPS with the current version and 32 with the experimental. :+1:

For asteroids with 1500 asteroids example, I’m getting far better results if:

  • You ensure the first parameter to the collision between “player_bullet” and “larg_asteroid” is “player_bullet”, which is already :slight_smile:
  • You move the collision test out of the “repeat for each instance”:

Indeed the issue is that with the original solution (collision condition as a sub event of the for each), you:

  • move an asteroid
  • test the collision (which means that the spatial data structure must be updated)
  • move an asteroid
  • test the collision (which means that the spatial data structure must be updated)
  • move an asteroid
  • test the collision (which means that the spatial data structure must be updated)
  • … and this 1500 times per frame!

while if you move it out, you know:

  • move an asteroid (1500 times)
  • test the collision (which means that the spatial data structure must be updated) only once.

So two things:

  • As mentioned before, I think the game engine should surely take a look at the number of objects and smartly chose the first object of the collision condition. But I have to check that this test itself is not lowering performance. Also this must not be done if the condition is inverted (this would break the semantic of the condition).
  • The spatial data structure is much more “fragile” in case of running collision condition a lot after moving objects.

In theory, the asteroids example itself should be fixed: there is no need for the “For Each” to be so much at the top of the events. As possible, “For Each” should always be used as a last resort, as a sub event of the collision, not the reverse.
In practice, I’m not sure how to guard against these mistakes. Analysing the events to warn about this? Ideally I would like the spatial data structure not be not worse than the old version when a “degraded” case like this is happening - not sure how doable is this.

1 Like

Maybe on the first frame of a scene analyse the number of collision check by adding +1 to a variable each time the collisions are checked, and if it exceeds a certain point then enable “legacy collision checking”

“In game analysis” like the one your describe is an option - but not on the first frame because you likely don’t reach all the conditions for collision (not bullet fired, enemy not spawned, etc…). More generally, the risk with instrumenting the game at runtime is that it’s itself a performance overhead (measuring the time, analyzing them) and can create strange results (“why is my game slow then suddenly fast”… or the reverse in case of wrong optimization!)

So I rather aim for a solution that works well in the case where it’s properly used (collision checked between a lot of objects), adapt to corner cases (properly choose the objects that are in larger quantity for the spatial data structure) and if possible is not making performance too bad when improperly used (like in asteroids).
But this last bit is tricky, because it’s not obvious how to fallback to a legacy collision checking (I did replace the spatial data structure by a naive list, like what was done in the legacy collision checking, but there is still overhead that make performance worse in asteroids).

One way to go about it is implement exceptions maybe when certain conditions actions are not allowed to be used like collision checking in a for each loop or in a sub event of such loop. When the user select the collision checking to add directly to a for each event or to a sub-event the OK button could be not clickable and display a message why.
In case an already existing event contain collision checking and the user would drag the event to be a sub-event of a for-each event or drag directly the condition to drop it in to a for each event, it could also be something that not allowed and could display a message the moment the user trying to drop the event.

So it would require the IDE to constantly look for these exceptions when the user change the events. Not sure how much work I am talking about and how much resources would be used, I guess it could be a problem when you have lots of events. Wondering if there is any way GD knows if an event has a parent and if you can pick the highest in the hierarchy or look for a for each event straight away higher in the hierarchy without the need to iterate through all events and tracking it down each time the user change something. That could be a solution to keep the performance good I guess.

Because we can also create instances during run time I think it should be handled during run time. One way I can think about this is to initially ignore what the user selected and instead check the number of instances of both objects involved and execute the event as it fit the spatial data structure better “put smallest quantity first”.

Or adding in code generation a step where it checks for each scene for the number of actions that are present for collision checking, and if there is toggle a bool passed in the object data?

In the end I think the best would be to leave it as a scene option in the scene properties so that user can enable those other collision mechanism per scene if it is faster for their specific case.

Indeed better but at least on my end it is still worse compared to the current stable version.
I’m getting 17-22 FPS in the experimental and 39-42 FPS in the current stable with the fix applied.

Yes, I think it is a good idea, for now it seems to be the most useful when you comparing many vs many, in any other case we are getting far worse results compared to the current version.
But as I mentioned because we can create and delete instances during run time, it may be not constant and for best experience I think should find a way to handle this at run time and let the engine decide how to do it. But in case it is too much trouble I agree to make it an option somewhere to toggle on and off because it is certainly improve performance a lot when we comparing many vs many :+1: