Page 1 of 1

Make entities collide only with static mesh?

Posted: Thu Jul 19, 2012 12:22 pm
by Garold
When I kill an enemy I break it apart into pieces. Each piece is a physics box. I create them when the enemy is created. When the enemy dies I add them to the space. After 30 seconds I remove them from the space. When the enemy is re-spawned and dies the boxes are once again added to the space, and the cycle continues like that.

The problem I have is: if I kill many enemies at the same time, I am getting low frames per second.

Is there a way to speed this up? I thought one solution would be to make the boxes collide only with the static mesh group and not with each other or anything else. If so, how would I go about doing it? I have added collision rules so that one entity would ignore another, such as a grenade ignoring the body of the character, so he doesn't stand on it.

Like this

Code: Select all

CollisionRules.AddRule(grenadePhysics, SM.Character.CharacterController.Body, CollisionRule.NoBroadPhase);
However If I have 25 enemies, each with 15 bones, I would need to create many collision rules. Nevertheless is that the way?

I would prefer to keep it as it is, with all the bones colliding with one another, as I like that the enemies can walk over the bones of others and also that a grenade can catch in the bones.

You can see in this video, what I am waffling about. You can skip to 6:00 to see the final result.


Re: Make entities collide only with static mesh?

Posted: Thu Jul 19, 2012 4:20 pm
by Norbo
Using CollisionGroups would solve the issue of having to create a bunch of separate rules. Instead of a combinatorial explosion, just set the bones' entity.CollisionInformation.CollisionRules.Group to a shared BonesGroup. Then, specify a rule NoBroadPhaseRule between the BonesGroup and itself, and the BonesGroup and the CollisionRules.DefaultDynamicCollisionGroup. The bones will then only collide with other collision groups, like the CollisionRules.DefaultKinematicCollisionGroup which contains any kinematic object and the static mesh.

These rules can be added using a helper method:
CollisionGroup.DefineCollisionRule(BonesGroup, CollisionRules.DefaultDynamicCollisionGroup, CollisionRule.NoBroadPhase);
CollisionGroup.DefineCollisionRule(BonesGroup, BonesGroup, CollisionRule.NoBroadPhase);
However, this may not even solve the performance issue on the Xbox. The majority of the collisions were likely between the mesh and the bones anyway. To know if it's possible to keep all the physical interactions, more information about the nature of the slowdown is required. Some data collection options:
-The development version can be compiled with the PROFILE compilation symbol to expose per-stage timings.
-Run a full profiler on the game to drill deeper than per-stage timings; check if there's any unexpected hotspot in the code. Spending a long time trying to improve performance on the wrong thing would be silly :)

A couple of possible general improvements:
-Reduce complexity of any convex hulls used by the bones to see if it helps. If switching to boxes or spheres helps a lot, then the convex hulls were likely too complicated. If the bones are all simple primitives already, this probably won't be a productive avenue.
-Make things go to sleep faster. Use a higher Space.DeactivationManager.VelocityLowerLimit and a lower Space.DeactivationManager.LowVelocityTimeMinimum.

If the simulation ends up just being too large for the Xbox, then trickier methods can be used. Instead of keeping every bone around for a fixed time, maintain a priority queue of bones. As more bones spawn, compare it against some threshold of bones you know the Xbox can run. If it is exceeded, start removing low-priority bones from the space. This stabilizes the performance of the game while keeping the most important stuff around (the stuff you just killed and the bigger pieces).

However, even if it runs fast enough, there might be an issue: if you plan on implementing networking in the future, it is likely that the bones will still need to have their collision rules adjusted (no player-related collisions) to prevent the need to synchronize them across the network.

Re: Make entities collide only with static mesh?

Posted: Fri Jul 20, 2012 6:59 pm
by Garold
Thank you for your detailed answer, I decided to keep the collisions, as you say they are probably mainly colliding with the mesh. So I tried your other suggestions.
If the bones are all simple primitives already, this probably won't be a productive avenue.
I was already using boxes for the physics objects, but one thing I did change was making their width and depth different dimensions, this made them roll less, they did not keep their momentum, especially when rolling downhill.
Use a higher Space.DeactivationManager.VelocityLowerLimit and a lower Space.DeactivationManager.LowVelocityTimeMinimum.
I did this and got a substantial improvement in performance and also how the game looks, so a win win. I changed to the values below. The bones now go to sleep quicker, roll less and look more bone-like.

Code: Select all

Space.DeactivationManager.VelocityLowerLimit = 1f;
Space.DeactivationManager.LowVelocityTimeMinimum = 0.05f;
Run a full profiler on the game to drill deeper than per-stage timings;
I can't afford to buy Visual Studio, so I downloaded a trial version of ANTS. I am still learning to interpret the output, but I did notice my game spent too long calculating bone matrices and drawing. So I reduced the skeleton's number of bones by getting rid of all but one finger bone. Instead of 47 animatable bones, now there's only 25, but still 15 physics bones.

My old laptop can't cope with running ANTS and killing skeletons at the same time. So where the ANTS output declares parts of your code as "HOT", I don't know if that's just a symptom of my poor processing power.

Either way in a combination of ignorance and enthusiasm here's a screenshot of the ANTS output.

Full size http://cloneofduty.files.wordpress.com/ ... ants-1.png

Image

Re: Make entities collide only with static mesh?

Posted: Fri Jul 20, 2012 7:46 pm
by Norbo
"HOT" labels in ANTS just mean that a code path is responsible for a notably large amount of time relative to other things. Running a profiler typically ruins multithreading, so the related big overhead times are expected. The ratio of physics stage times are pretty normal, so I don't expect any extremely unusual circumstances are lowering performance. You may find the results easier to read/use if the engine isn't using multiple threads. That could help expose some other bottleneck.

Re: Make entities collide only with static mesh?

Posted: Fri Jul 20, 2012 10:46 pm
by Garold
Thanks.

I disabled multi threading by commenting out this code:

Code: Select all

//if (Environment.ProcessorCount > 1)
//{
//    //On windows, just throw a thread at every processor.  The thread scheduler will take care of where to put them.
//    for (int i = 0; i < Environment.ProcessorCount; i++)
//    {
//        Space.ThreadManager.AddThread();
//    }
//}
I ran ANTS again, and with my limited knowledge I noticed it highlighted CHECKMATH functions, so I removed the CHECKMATH compilation symbol. The game definitely ran faster. What are the consequences of this action? It seems too good to be true, but then again it is optional?

On a non ANTS point, I notice that the game slows down when I kill skeletons in close proximity to each other. Also the odd bone instead of dropping to the floor normally due to gravity, is instead launched into the air as though a large impulse has been applied.

Could adding boxes that overlap cause a slow down?

Here's another video:

Re: Make entities collide only with static mesh?

Posted: Fri Jul 20, 2012 11:11 pm
by Norbo
I ran ANTS again, and with my limited knowledge I noticed it highlighted CHECKMATH functions, so I removed the CHECKMATH compilation symbol. The game definitely ran faster. What are the consequences of this action? It seems too good to be true, but then again it is optional?
The CHECKMATH symbol is just for debugging purposes. It helps find NaNs and infinities closer to the source rather than later when they propagate through the simulation and crash it some other way. Removing it is fine- it should not be defined for a build intended for performance. I typically keep it defined only on my debug configuration since the debug configuration is quite a bit slower than the release configuration anyway.
On a non ANTS point, I notice that the game slows down when I kill skeletons in close proximity to each other. Also the odd bone instead of dropping to the floor normally due to gravity, is instead launched into the air as though a large impulse has been applied.

Could adding boxes that overlap cause a slow down?
If there's a lot of objects overlapping, the penetration correction system could give them a boost. Explosive separation would require a large number of overlapping objects configured in such a way that the relatively small correction speed adds up between each pair.

The simulation cost is roughly proportional to the number of pairs, so if you can avoid unnecessary overlaps, it would be a good idea.

Re: Make entities collide only with static mesh?

Posted: Sun Nov 04, 2012 11:30 am
by Garold
I know this is an old post. I just wanted to say thank you.

I am optimising my code and I finally just got round to putting in the code you very first suggested. I didn't add it as the game was running fine with the other changes I made. I had a problem with the character colliding with the dead skeletons' bones and the collision group fixed it, but also made the death explosion better.

Code: Select all

CollisionGroup BonesGroup = new CollisionGroup();

physicsHeadShape.CollisionInformation.CollisionRules.Group = BonesGroup;
.
.
CollisionGroup.DefineCollisionRule(BonesGroup, CollisionRules.DefaultDynamicCollisionGroup, CollisionRule.NoBroadPhase);
CollisionGroup.DefineCollisionRule(BonesGroup, BonesGroup, CollisionRule.NoBroadPhase);