Over the past week or so I've been working on getting better collision shapes for the hitboxes for the 'mon in my game. In doing this, I found that the frame rate seemed to noticeably decrease compared to just using a large capsule for the hitbox. So I decided to do some rudimentary benchmarking of the different collision shapes Bullet offers.
For my hitboxes, I added support for the btMultiSphereShape
, a convex hull of a set of spheres, to U3D[^1] and my (forked) Blender Exporter. This shape is pretty nice – a few spheres are able to nicely model segments of the body (roughly corresponding to the animation skeleton: upper arm, fore arm, head, neck, chest, waist, etc.) for collision purposes. It's not quite as exact as a triangle mesh, but it's actually solid, not hollow, so fewer missed collisions should happen, and it's pretty quick to make with Blender's geometry nodes. With support added, and examples for my two characters for the mini battler demo/game I'm working on, the initial tests seemed to give a drop in frame rate from about 100 to 70, give or take. So I felt I needed to try benchmarking what was going on (as the profiler did indicate a lot of time spent in some seemingly related bullet physics functions).
For the benchmarking, I wanted it to be easy for me to write and fairly representative of an actual game scenario. So I simply adapted the Physics Stress Test Sample to use different shapes, which can be set through command line arguments. Further, the number of rigid bodies that are created can be set through an argument so I can ascertain the maximum number of shapes I should aim to use at one time. Lastly, I wanted to get an idea of how many spheres it's okay to use per multi-sphere hull, and I also wanted to compare to the alternative of using a btCompoundShape
with multiple sub-shapes[^2] instead of the multi-sphere hull. So the number of sub-shapes (for non-multi-sphere-hull shapes) or spheres (for multi-sphere hull) is also set by an argument.
This leads to the following results when I run the benchmark on my (fairly weak, old i5) desktop. Take them with a grain of salt, as there are a few issues with the benchmark:
Even with the limitations, there are still some conclusions we can draw from the benchmark.
For my 60FPS target, with an additional 5ms budget for animations, visual effects, AI, etc., I can afford up to around 100 multi–sphere hull shapes (i.e. hitboxes) divided between all the 'mon in a battle. This should be sufficient for up to 6 'mon in a battle, assuming no more than 15–16 multi–sphere hull shapes for each 'mon. This is pretty reasonable: 2 per limb, 2 for the body, 1 for the neck, 1 for the head, maybe a few more for the tail (or maybe not – the tail may be too much of a handicap). Generally no more than 4 limbs, which gives 8+2+1+1+3 = 15, right where the benchmark suggests I should aim.
[^1]: U3D is the fork of Urho3D I am now using after the original project fell apart.
[^2]: wrapping in a btCompoundShape
is handled for us internally by U3D if we just add multiple CollisionShape
s to a Node
.