Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental object collision and positions handling improvements #1393

Draft
wants to merge 22 commits into
base: master
Choose a base branch
from

Conversation

4ian
Copy link
Owner

@4ian 4ian commented Jan 21, 2020

This enables RuntimeObject positions to be managed by a spatial data structure (a "RTree", called RBush too here), allowing to speed up collision/separate objects/raycast on a large number of objects.

This is still highly experimental, and a large PR. I want mainly to ensure that there is no regression in terms of behaviors in games, and no large performance regression too.

Performance benchmarks (average frame time):

  • Collisions benchmark when not hovering the ~1200 boxes with the ~1200 cursor objects:

    • Old version: 120ms
    • New RTree: 2ms
  • SeparateObject

    • Old version: 250ms
    • New Naive: 69ms
    • New Rtree: 25ms
  • Distance test (Distance between objects benchmark)

    • Old: 52ms
    • New Naive: 66ms
    • New Rtree: 12ms
  • "Collisions with creation and deletion benchmark"

    • Old: 30ms
    • New Naive: 38ms
    • New RTree: 13ms
  • "Cursor on object benchmark"

    • When everything moves:
      • Old: 40ms
      • New Naive: 32ms
      • New RTree: 52ms (not that bad considering that this is the worst case scenario for the RTree)
    • When nothing moves:
      • Old: 20ms
      • RTree: 16ms
  • Raycast benchmark:

    • Old: 50ms
    • New Naive: 85ms
    • New RTree: 65ms
  • "Point inside object benchmark":

    • Old: >200ms
    • New Naive: 82ms
    • New RTree: 56ms
  • markObjectAsDirty should be called also when setWidth/setHeight is called for most objects (much like this.hitBoxesDirty).

Todos:

  • See if we need to do right now an implementation where we can disable the RTree for some objects
    • If yes, surface in the UI and in events the ability to enable to disable the usage of a RTree to store positions of each object.

Clean-up todos:

Future:

As GDevelop is a generic game engine, there can be cases where the usage of an RTree can be actually too costly and slow down the game compared to not using one. We would probably need to expose this is a setting somewhere in the IDE.

Trying this

Changes in this PR should be invisible to the user. You probably won't notice even difference in your game, unless you're in the case where the RTree can be speeding up things for you (lots of collision check between lots of objects) or slowing this down (few checks but lots of objects moving).

For now, I want to ensure the stability of this - there is room for optimisation later. In the worst case, this could be disabled by default and enabled in the UI on a case by case basis. For now, it's activated for all objects.

To help me, you can simply download the GDevelop versions below. They are beta 88 with this PR applied:

⚠️ I recommend not to use this version for making your game. Stay on the latest stable version (beta 88), just install this one to try your game and see how it behaves.

Once you have this version, try to open your game and launch it:

  • If your game is visibly broken, check if you can send me the part that is broken with a good description of what's wrong.
  • If it's working properly, let me know if you find any performance difference (large improvement or regression). You may use the GDevelop profiler, running it for a few seconds and then look at the average time to render a frame in your game - though this may be hard to compare as this depends a lot on other factors.

…xisting object position

This can happen if a gdjs.RuntimeObject is deleted from the scene: it's marked for deletion,
but still used by the current events, which can pass its id to the gdjs.ObjectPositionsManager
(which won't have an associated ObjectPosition for its id, as it would have been marked for deletion
and really deleted at the next call to "update", which happen at any query like collision handling).
Remove "GDJS/tests/games/Collisions with creation and deletion benchmark.gdg.json" as now already existing in GDJS/test/games/memory-benchmarks
… improve perf

* Use a slightly more complex object for ObjectIdsSet to be able to quickly clear the set
* Fix bug where some objects were considered for pointsTest while not in the set of object ids to test.
@rishabhabhani
Copy link

A few questions I'd like to ask about this.
Is RTree a structure that runs on a separate thread or the same as the others.
If it does run on another, is it designed with the objectives in mind or be extensible?

@4ian
Copy link
Owner Author

4ian commented Mar 22, 2020

JavaScript is single threaded, so runs on the same thread as the rest. Web-workers or wasm could be used to maybe have it running on another thread, but it was not a goal in this implementation (there is more complexity to achieve this).

@Silver-Streak
Copy link
Collaborator

@4ian has the efforts around this been dropped? It seems like your checklist is mostly complete, and I'm sure people would love collision performance improvements. (Especially with Davy's other outstanding PRs)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants