Projectiles 'Hopping' over objects instead of cause a collision

Hey everyone, I’m having a problem I can’t figure out how to solve. I have two objects, a Projectile and an Enemy. Both have a BoxCollider2D and a Rigidbody2D setup as below:

7877290--1001665--upload_2022-2-7_18-46-28.png

The problem is the collision event isn’t occurring because the movement of the Projectile is essentially ‘hopping’ over the Enemy in one frame. To visualize it these two screenshots represent one frame after another:

7877290--1001668--upload_2022-2-7_18-47-57.png

7877290--1001671--upload_2022-2-7_18-48-6.png

They both have “void OnTriggerEnter2D(Collider2D other)” and the Projectile is propelled by either “Vector2.MoveTowards” or “GetComponent().MovePosition” (I’ve tried both to see if there’s any different effect).

I’ve been googling and testing different things for hours and can’t seem to figure out if there’s a way for an object to determine if it has passed through another object in order to trigger the collision. To be explicit if the two objects do touch it does definitely trigger as shown below:

7877290--1001680--upload_2022-2-7_18-52-34.png

I’ve tried changing basically every setting on the RigidBody and changing the methods the two objects are moved by, but nothing I seem to test works.

Is there something I’m missing about being able to detect this sort of collision?

Cheers

As long as you set collision to continuous on the RB and you are moving the RB correctly (see below), it should work.

With Physics (or Physics2D), never manipulate the Transform directly. If you manipulate the Transform directly, you are bypassing the physics system and you can reasonably expect glitching and missed collisions and other physics mayhem.

Always use the .MovePosition() and .MoveRotation() methods on the Rigidbody (or Rigidbody2D) instance in order to move or rotate things. Doing this keeps the physics system informed about what is going on.

With a wheel collider, use the motor or brake torque to effect motion.

Projectiles can be tricky. If they go too fast, they pass right through everything. If they go too slow they don’t seem that realistic. A few things you can do:

  1. Already mentioned and that is continuous should be set on the rigidbody for CD. It will probably help if it was a dynamic and not a kinematic rigidbody. Easiest solution to try as well.

  2. Use raycasts instead if you need fast projectiles. If its fast enough it might not even get rendered anyway, so then why waste processing it when one cheap raycast does it.

  3. Combine raycasts/linecast and a physical projectile. Determine how fast it can travel between frames and look either ahead or behind that amount to see if a collision will/has occurred. Continuous does something like this and is why it’s the first suggestion, this should be your last option.

1 Like

I changed the code to move everything using the RigidBody in FixedUpdate, as such:

rb.MovePosition(rb.position + targetDirection * projectileSpeed * Time.fixedDeltaTime);

I’ve set the RB on the Projectile as:

7878940--1002070--upload_2022-2-8_9-17-42.png

Both the Enemy and the Projectile are being moved using the RB physics but the problem still occurs. I’ve tried swapping the two objects both and individually from Kinematic to Dynamic and it didn’t make a difference. The collision isn’t being detected when the Projectile moves through the Enemy in a frame.

From everything I’ve read in the documentation and from my own research suggests it should work, but it’s not.

Your projectiles need to be Dynamic body-mode using Continuous. A Kinematic won’t stop when it touches something because it’s Kinematic i.e. it doesn’t have a collision response.

The reason to set a Kinematic body to use continuous is so it’d contact a Dynamic body correctly.

Why are you using explicit position movement on a Dynamic body? You can just set its velocity for a projectiles. Typically you’d use MovePosition on a Kinematic body.

Also, for projectiles that are kinematic, it’s often far better to perform a cast test to see what it’d hit. There are plenty of queries to allow you to do this.