Too many objects optimization (spatial partitioning)

Hello all,

Has anyone else encountered this issue with spatial partitioning (I think its called that?)

What happens is, instead of this working on the entire map, it only works one one grid block (random one I think) and the surrounding ones, the rest of the objects that are not in this 3x3 block area are ignored and their collisions dont count.

code

Grid system off

Grid system on

Well, you don‘t pick a specific Gunslinger in your last „For each Bullet“-Event.

So each Bullet grid value minus the grid value of your first created Gunslinger gets compared to <= 1.1, which totally depends on which Gunslinger is Gunslinger[0], and the chosen size of your grid. This leads appearently to the resulting explosions in the lower half.

What do you want to do and what is your issue?

If you simply want to only pick all Gubslingers in the same cell, as each Bullet, you should do (careful, freestyle syntax incoming):

For each Bullet
Pick Gunslinger with GridX/Y = Bullet.GridX/Y
And check collision.

That way you decrease the number of collision checks based on your grids cell-size.

What I didn‘t include there, was the neighbouring cells. So if an objects collision mask overlaps into a cell, but its center point is not, then this object would not be checked for collision. That might be okay, for your small looking sprites, since it is only edge cases. But you can ofcourse add the edge neighbors (5 cells total) or even the ones at the corner (9 cells total).

The implementation could be to also include Gunslingers with GridX/Y of -1,0,+1 for each direction respectively (conditions coupled by OR)

Repeats can become inefficient with large number of objects.

The repeats you have are unnecessary. The first 2 events do not need a repeat for each object. You can just use an unconditional event with the actions to calculate gridx and gridy. The values calculated for each object will be based on only that object’s position.

For the collisions, you also do not need to do a repeat for each object. So event with:
Variable Grid is false
Bullet is in collision with Gunslinger

will only select the bullets and gunslingers that collide with each other. There’s no need to repeat.


Just because you’re using a grid doesn’t make the problem you encounter an issue with spatial partitioning. If GDevelop is using spatial partitioning for collision detection, it’ll be doing it for each object it works with, not your grid.

Because spatial partitioning is a way of dividing up space into smaller regions so that objects only need to deal with nearby objects instead of everything at once.

As for why only a block of bullets explode, realise floor returns an integer, and the difference between integers will be another integer. So the gridx and gridy values will be 0, 1, 2, 3… Checking whether it’s less than or equal to 1.1 is pointless. Those differences will only be 0, 1, 2, 3 etc.

So it could just be coincidental that the girdx & gridy differences do not meet the threshold.

For example, say the grid was 64x64, and Gunslinger.CenterX()=127 and Bullet.CenterX()=128 and the condition is Gunslinger.gridx-Bullet.gridx < 1.

They are right next to each other, but the gunslinger.gridx = 1 and bullet.gridx = 2, and the condition won’t be met.

Yet if Gunslinger.CenterX() = 64 and Bullet.CenterX()=127, then they both have a gridx value of 1, even though they’re nearly a whole grid size apart.


So for that last event,you may be better off using a standard event with the 2 conditions:
Bullet is in collision with Gunslinger
abs(Bullet.CenterX() - Gunslinger.CenterX()) < grid.size * 1.1

That may solve your problem.

And get rid of all those repeats.

1 Like

You are right, that the conditions should not be inside the repeats. But „Create Explosion at each collided Bullet center“-action still needs to cycle through each instance of bullets, that collided, right?

Hello all,

Apologies for the late reply.

the 1.1 should have been a “1” I added the 0.1 out of desperation basically…you know, just in case.

I have to keep the “if less than 1” to make sure it checks if the objects are in the same grid block or an adjacent ones, I cannot just check if its in the same block because then neighboring blocks will not be checked.

The current issue, as pointed out by you also, is that I have no way of letting Gdevelop know that it has to check all gunslingers…
Any idea how to do that without a “for each gunslinger” inside “for each bullet”?

It will do all gunslingers if they’re in the scene.

If you use a normal event with the condition "Gunslinger in collision with Bullet", then the actions will only be applied to the Gunslinger and Bullet objects that meet the condition. No need to iterate for each bullet and then for each gunslinger.


If you’re still having trouble, you could zip up your project, put it on a shared drive and share the link to it. Then I’ll have a look into it later in the evening. Share the link in this thread or PM me.

Hello again,

Thanks for your time!

Heres the project

The thing is that, it doesn’t seem to cycle through all the gunslingers currently.
I’m assuming it only happens for the first created one? And the the explosions happen only in 3x3 block area around that one.

each block is 200 pixels, it is set in a global variable in case you’d want to change that one as well

There are some other stuff in there too, I’ve been trying…

So, the issue appeared to be the order of conditions:

These events:

Create these explosions:


Shifting 1 condition like this:

Resulted in:


And then there are a few other things:
  1. The explosions are continuously being created until the “start explos” is clicked again. This is not a good thing
  2. The continuous creation of explosions is seriously reducing the frame rate.
  3. The repeat for each bullet is unnecessary, Instead these events will do the same job but more efficiently by preventing the repeated creation of explosions:


Yes, those are all the events you need.

Resulting in:


Further suggestions:

Remove these 2 events - they are getting run every game frame, which is pointless unless:

And add the actions here instead, which is a much better solution:

2 Likes

Well, useless to continously update the grid, until your objects are moving. Because then they might move from one grid cell to another one. Then you will need to update the gridX/Y. But still not every frame and not all of them.

1 Like