FPS Projectiles: The matter of collision-implementation

As a side-project I’m making a small retro-FPS. So far, things are going fairly well, I think.

At the moment all collision-related matters are being handled by Panda’s built-in collision system.

But there is one thing that I’m yet troubled by: the question of how to handle collision for projectiles. Specifically, non-hitscan projectiles, of the sort that fly through the air, and that may potentially be avoided.

Now, the obvious way to implement such collision is to give each projectile a CollisionSphere. However, depending on the size and speed of the projectile and the frame-rate of the game, there’s a risk that projectiles might “skip over” an object.

I could activate the “respect previous transform” functionality (as described here).

However, the documentation indicates that this feature is only implemented for CollisionSpheres colliding into CollisionPolygons, which is fine for projectiles hitting walls, but not for projectiles hitting characters–those last currently use CollisionCapsules.

I’m also not sure of what the overhead of this system might be. I was preparing to experiment to determine whether or not it is too heavy when I discovered the “sphere-into-polygon” limitation mentioned above.

Another approach might be to model the projectiles as CollisionCapsules. This would make the projectile longer–and thus less likely to skip over things–without increasing its width or height.

However, if the capsule is of fixed length, then there’s the risk that collisions could happen “behind” the projectile, which might undermine the apparent fairness of projectile collisions. Conversely, if I update the capsule-length each frame then there’s additional overhead, and I don’t know whether it’s likely to perform well.

Finally, I could implement my projectiles as CollisionSegments. These would be treated much like the capsules, above, likely updated each frame. Again, I’m not sure of the overhead, although my instinct is that they should be cheaper than capsules.

Right now I’m not at all confident of which way to go here–hence this thread. What do you think? And are there any approaches that I might have missed?

(Of course, some of the overhead could be reduced by implementing my projectiles in C+±-but right now I’d rather not do that, especially for a side-project. I’d rather stick to Python.)

I am not intimately familiar with this system, but I believe that what “respect previous transform” does is that it turns a sphere-into-polygon test into a capsule-into-polygon test; that is, the capsule representing the volume made by sweeping a sphere along the distance it travelled during the last frame.

We could implement this feature for sphere-into-capsule. We already have a capsule-into-capsule test, so we could just copy-paste code from there. Feel free to file a feature request for this.

At least in theory, a segment-into-capsule test is equally as expensive as a capsule-into-capsule test. This is because the intersection test between a capsule with radius r1 and a capsule with radius r2 is the same as the intersection test between a capsule with radius (r1 + r2) and a line segment. In other words, both tests are equivalent to checking whether the distance between their center line segments
is smaller than the sum of their radii. So, I don’t think you will gain advantage from using a segment.

Interesting–from the documentation, I had the impression that it worked iteratively, moving the sphere a little at a time from one point to the next.

Hmm… It’s tempting, but waiting for a new version might hold up the project… We’ll see.

Ah, that’s interesting! So then, the question becomes this: is there a difference between expense of setting the start- and end- points for a segment, and that for doings the same with a capsule?

(Both seem to have methods for setting their start- and end- points.)

If they’re similar, then perhaps a capsule is the better option: One potential issue with the segment approach which I previously forgot to mention is that I don’t know how it behaves when a high frame-rate results in an extremely short segment. Do precision issues cause problems?

A capsule, on the other hand, presumably reduces to a sphere when its length is effectively zero, and thus still has a well-defined form.

Changing a capsule’s start and end point is virtually free. I would just use a capsule for this. You could still file the feature request and switch to Panda’s implementation later if you find that the method is effective.

Okay, the capsule approach sounds good then, and I’ll hopefully hold the feature request in mind if it fails. Thank you! :slight_smile:

Actually, I just tested it, and it looks like sphere-into-capsule is supported just fine with respect-prev-transform enabled. I recommend just using the built-in test with a sphere for the projectile solid then!

I will update the documentation to properly reflect which solids are supported.

1 Like

For the record, it looks like all of our “into” solids support collisions from CollisionSphere with respect-prev-transform checking (except CollisionPlane and CollisionInvSphere, but they don’t need to because there’s no way to define a linear path that takes a sphere “through” those solids).

1 Like

Oh, excellent! Well, I daresay that I’ll do that, then–thank you! :slight_smile: