Page 1 of 1

Poor performance when ghost object overlaps many btBoxShapes [with video]

Posted: Sun Nov 11, 2018 12:04 am
by PcChip
Hi,

In my game, every unit (in this video, drones) has its own rigid body shape (in this case, tiny spheres) to control its own motion, and they also all have a large btPairCachingGhostObject to act as a "detection range" - to detect nearby enemies to target

This works perfectly in most situations, however today I noticed that when building a huge grid of walls (each is just a btBoxShape rigid body with mass 0) , as soon as a few of the drones' ghost objects overlap the mass of walls, performance tanks.

I actually already tried this suggestion: https://github.com/bulletphysics/bullet3/issues/1283 and unfortunately it didn't help.
(I used a derived needsCollision and needsResponse as the author did on Github, however if I used his needsCollision, the ghost objects stopped working entirely. I could only use his needsResponse and have them still work)

A few questions:
1. Is a ghost object even the right way to detect if enemies are near each unit? If not, what would work better?
2. If ghost objects are the right answer, am I using them correctly?
3. Has anyone else ran into this issue before?

Here's the video: https://www.youtube.com/watch?v=UnOQ_CBa87g
Note when the drones fly over all the boxes, performance tanks and eventually catches up again


snip from each drone spawning code that creates the ghost object:

Code: Select all

	if (canAttack)
	{
		//attackRange Ghost Object
		instanceData[thisLocation].myAttackRangeGhostObject = new btPairCachingGhostObject();
		instanceData[thisLocation].myAttackRangeGhostObject->setCollisionShape(myAttackRangeGhostShape);
		instanceData[thisLocation].myAttackRangeGhostObject->setWorldTransform(btTransform(btQuaternion(0, 0, 0, 1), btVector3(spawnLocation.x, spawnLocation.y, spawnLocation.z)));
		instanceData[thisLocation].myAttackRangeGhostObject->setCollisionFlags(instanceData[thisLocation].myAttackRangeGhostObject->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);

		world->physicsModule->dynamicsWorld->addCollisionObject(instanceData[thisLocation].myAttackRangeGhostObject, COL_FRIENDLY_SENSORTRIGGERS, friendlySensorTriggersCollidesWith);
		instanceData[thisLocation].myAttackRangeGhostObject->setUserIndex(-100 - myIndex);
		instanceData[thisLocation].myAttackRangeGhostObject->setUserIndex2(-100 - thisLocation);
	}

Thanks for any suggestions you may have!

Re: Poor performance when ghost object overlaps many btBoxShapes [with video]

Posted: Mon Nov 12, 2018 3:15 am
by drleviathan
I wouldn't be surprised to learn that several btPairCachingGhostObjects each overlapping several other objects could put a heavy load on Bullet's simulation. Here is some ideas that might be helpful:

(1) By default Bullet will update every Aabb of every static object every substep. Normally this default behavior becomes a noticeable performance bottleneck when someone starts adding thousands or tens of thousands of static objects to their simulation, however it seems to me it might also impact the performance of many btPairCachingGhostObjects that overlap many static objects. To disable automatic updates to static Aabb's every substep you can use btCollisionObject::setForceUpdateAllAabbs(false), however when you do this: if you ever move a static object to a new position you must manually updates its Aabb in the broadphase before the next step, else dynamic things will not collide correctly with it.

(2) If you set the collisionGroup and collisionMask correctly for your objects you can avoid broadphase overlaps between GhostObjects and things they don't care about. Are the drones actually interested in all of those static boxes? You should also set the bits so that GhostObjects don't collide with other GhostObjects, nor with: the ground, friendly drones, etc (as long as the drones truly don't care about such objects). This might save CPU cycles.

(3) Perhaps you could try not updating the GhostObjects every frame. If the drone is moving slowly enough, and the GhostObject is big enough, you might be able to update them every N frames, or maybe timebox your GhostObject updates and only update a subset every frame. In other words: provide a way for an overload of searching drones to fail gracefully: trade frame rate robustness for detection accuracy.

Re: Poor performance when ghost object overlaps many btBoxShapes [with video]

Posted: Mon Nov 12, 2018 11:53 pm
by PcChip
HI DrLeviathan, I was hoping you would show up!

regarding (2) - I believe I have the collision groups and filters all sorted out, and I'm pretty sure it was you that helped me with that several months ago :) Indeed every drone is actually interested in every box, because each box is a wall segment. In games like Factorio, enemies come up to your walls and start attacking the nearest wall segment - I want to do something similar

regarding (1) - I will try this, as I don't plan on moving static (mass 0) objects - they are buildings/turrets and if they're destroyed I'll remove the static object from the simulation

regarding (3) - why didn't I think of that?? I just set them to update only twice a second, and the performance is better. It's not perfect, it still dips, but it's better - and that's a start. Thanks!

My main concern was to figure out if this was a fixable problem or if I needed to re-think the way the entire AI / enemy detection mechanism works from scratch. I'm leaning towards leaving the system as-is and trying to tweak it to make it faster

Re: Poor performance when ghost object overlaps many btBoxShapes [with video]

Posted: Thu Nov 15, 2018 12:29 am
by Erwin Coumans
>> 1. Is a ghost object even the right way to detect if enemies are near each unit? If not, what would work better?

Another option is to use an broadphase aabbTest query first. This may be good enough, but you can perform a more accurate query if needed on the objects returned by the aabbTest (and the query object).

Code: Select all

cb.m_closestDistanceThreshold = closestDistanceThreshold;
this->m_data->m_dynamicsWorld->contactPairTest(setA[i], setB[j], cb);
See around https://github.com/bulletphysics/bullet ... .cpp#L6719 for some example code.

Re: Poor performance when ghost object overlaps many btBoxShapes [with video]

Posted: Thu Nov 15, 2018 4:16 am
by PcChip
Hey Erwin, thanks for commenting!

To be honest, I'm not sure how or where I would use that code, would I need to override a default Bullet class in order to do that?

I currently don't have any callbacks set up, and just do a normal stepSimulation every frame - where would I put that code?

Re: Poor performance when ghost object overlaps many btBoxShapes [with video]

Posted: Tue Dec 11, 2018 2:56 am
by PcChip
would it be more efficient for me to switch to using a btGhostObject instead of a btPairCachingGhostObject?

I don't care *where* the collisions happen, I only need to know if the buildings are inside the spherical attack range of the drones