Arrows tunneling through enemies

About 25% of the arrows players fire in my game ( https://www.empireofember.com/ ) go through enemies.

The enemies are jointed body state controlled by an animator. On each body part I have a rigidbody set to kinematic, a collider, and a character joint. At runtime, when the player shoots an arrow, I set collisionDetectionMode to ContinuousSpeculative and the arrow itself is set as ContinuousDynamic.

From Unity - Manual: Rigidbody component reference
Continuous Speculative: … “This is also the only CCD mode that you can set kinematic bodies.”
Continuous Dynamic: … “Use sweep-based continuous collision detection against GameOjects set to Continuous and Continuous Dynamic collision. It will also use continuous collision detection against static Colliders (without a Rigidbody). For all other colliders, it uses discrete collision detection. Used for fast moving objects.”

So it seems like I have no choice but to use Continuous Speculative on the jointed characters. However, according to these same docs continuous dynamic only uses sweep based with Continuous and Continuous Dynamic.

All I want is for my arrows to reliably hit specific body parts on an animated jointed character, something thousands of other games have done. How do I do this?

Many physics problems in Unity are related to code, so what are you using to detect collision? Is it OnCollisionEnter? How are you moving arrows?

Without knowing much about your setup, one old and primitive but functioning way to solve the problem of reliable collision detection for high velocity objects is by doing a raycast\sweep from the current position to the destination point(right before movement) and checking if anything is in the way. See a myriad of different options on this page ranging from a simple ray to primitive collider casting Unity - Scripting API: Physics

That, of course, goes out the window if you move your arrows through rigidbody velocity.

I use OnTriggerEnter. Arrows move using the normal physics system the same as any other falling object. It seems ridiculous that I would need to use a Raycast, in that case what’s the point of providing Continuous detection modes?

It depends on the relative sizes of the objects involved. Regardless of the collision detection mode, you’ll always run into problems if an object is moving faster than its size. That is, if an object is 0.1 meters across, but moves faster than .1 meters per FixedUpdate, it can definitely go “through” objects and not trigger collisions. I don’t know how faster your arrows are relative to their size, whether the collider is the full length of the arrow or just the head of the arrow. But I generally always use manual raycasting for collision detection for fast-moving projectiles.

“Regardless of the collision detection mode, you’ll always run into problems if an object is moving faster than its size.” The docs indicate that for discrete collision mode, but not continuous. I believe this is either a bug or poorly written documentation.

In the end I made the arrows 2 meters long rather than 1 meter long. Normally the arrow would hit the shooter, but I I have code that makes the arrow ignore starting collisions and I have not seen the problem since doing that.

I’m not sure what technique you’re using, but I’d recommend looking at Physics.IgnoreCollision for that sort of thing. (https://docs.unity3d.com/ScriptReference/Physics.IgnoreCollision.html) It just tells the physics system not to handle collisions between two specific colliders. It’s very useful for ensuring that a player doesn’t get hit by their own projectile.

I what i do with projectiles(or any other body that is both small and fast moving) is keep them as discrete collision but do a raycast each fixed update from previous position to current position to see if we clipped though something (not physically accurate but unless a low update rate it works just fine)