Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question High Speed Projectile Collider Missing

Discussion in 'Physics' started by Zullar, Dec 2, 2020.

  1. Zullar

    Zullar

    Joined:
    May 21, 2013
    Posts:
    651


    I have a player with a collider and a projectile with a collider. When the projectile is fast it will intermittently miss the player. I am assuming one frame the projectile is on one side of the player and the next frame the projectile is on the other side of the player and no collision is detected.

    I believe Continuous Dynamic collision detection is intended to prevent this but it is not working.

    The players rigidbody/collider settings
    Rigidbody
    -Collision Detection: Continuous Dynamic
    -IsKinematic: False
    Collider:
    -IsTrigger: False

    The projectile rigidbody/collider settings
    Rigidbody
    -Collision Detection: Continuous Dynamic
    -IsKinematic: False
    Collider:
    -IsTrigger: True


    It's worth mentioning that both rigidbodies are awake and proper layers and such. If I slow down the projectile it hits 100% of the time. The faster it goes the less likely it is to hit.

    Also I need the projectile to be a trigger (I do not want it applying any forces and also I needs to pierce in some cases)

    The failure to collide happens if the projectile is moved by setting the rigidbody velocity to a value. It also fails to collide if the projectile is moved manually (i.e. transform.position += velocity * Time.deltaTime)

    Thanks in advance.
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,497
    I'd try moving the projectile using Rigidbody.AddForce with ForceMode.VelocityChange. Modifying Rigidbody.velocity overrides the value that was calculated by physics solver. You can enforce a specific velocity as follows:
    Code (CSharp):
    1. projectileRb.AddForce(expectedVelocity - projectileRb.velocity, ForceMode.VelocityChange)
    According to the documentation the player's collision detection should be "Continuous" instead of "Continuous dynamic". It also mentions that continuous collision works with capsule, sphere and box colliders only (but they should collide with static mesh geometry).
     
    Zullar likes this.
  3. Zullar

    Zullar

    Joined:
    May 21, 2013
    Posts:
    651
    Thanks for the ideas. I tried both those things but neither worked.

    The only thing that seems to work is changing the projectile from a Trigger to a non-Trigger. But this has 2 problems
    1: Trigger projectiles cannot pierce
    2: Targets and projectiles apply forces to eachother

    It seems that Triggers do not work with any form of continuous collision detection? That seems like a big oversight on the physics engine... so I feel like I am missing something otherwise I imagine many others would be having the same problem. Am I doing something wrong?


    I can work at band-aiding a few ways...
    -Elongate the projectile collider (i.e. lay a capsule down on it's side). At high velocities the projectile collider length should be speed/Time.fixedDeltaTime.
    -Remove the collider and manually perform RayCast in front of projectile.

    Both these bandaids introduce several issues... such as
    -overhead (having multiple projectiles performing raycasts every frame seems like a bad idea)
    -still missing fast moving targets
    -capsule colliders cannot be tall, long, and skinny. would have to use mesh or box collider?
    -detecting impact at the wrong location (with fast-moving projectiles even *if* the collision is detected it is often on the back side of the target and can give an incorrect collision location)
     
  4. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,549
    I believe you should be using Continuous Speculative - "Speculative CCD works by increasing an object’s broad-phase axis-aligned minimum bounding box (AABB), based on the object’s linear and angular motion. The algorithm is speculative because it picks all potential contacts during the next physics step. All contacts are then fed into the solver, which makes sure that all contact constraints are satisfied so that an object does not tunnel through any collision."
    https://docs.unity3d.com/Manual/ContinuousCollisionDetection.html
     
    Zullar likes this.
  5. Zullar

    Zullar

    Joined:
    May 21, 2013
    Posts:
    651


    Thanks for the help. Unfortunately no luck.

    I've tried many combinations.
    -Projectile rigidbody interpolation on/off.
    -Projectile collision detection Discrete/Continuous/Continuous Dynamic/Continuous Speculative
    -Projectile movement by setting rigidbody velocity
    -Projectile movement by applying force
    -Projectile movement by manually setting position every frame
    -Made target with and without rigidbody
    -Made target static and non-static
    -Made target kinematic/non kinematic
    -Made target's collision detection Discrete/Continuous/Continuous Dynamic/Continuous Speculative
    -Made target isTrigger both True and False

    Nothing seems to work. The projectile just keeps tunneling and missing collisions. It seems that Trigger Colliders don't work at high speeds :[
     
  6. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,549
    You could lower Project Settings->Time->Fixed Timestep.. the value is in seconds, so 0.0083 is roughly 120 physics steps/second, though you could try with a higher value first and see if that's enough.. it'll take some trial and error to find the right balance between accuracy and performance (as the lower the value, the more processing is required). Just keep lowering it until there's no tunneling. This will ensure that for example if your collider is 1 in diameter, it can travel up to a speed of 120/second without missing a hair (probably close to 240/second in the case of direct hits if the target collider is about 1 as well.. considering only part of it has to collide). Glancing blows will miss more often if it's not low enough.

    There's also the approach of raycasting your projectiles, which is worth the effort if you're up for it (since lower timestep probably hits performance more than the additional raycasts - you'd have to see for yourself, too many variables re implementation and project specifics to say that's always the case).
     
    MrMelSE and Zullar like this.
  7. Leohd

    Leohd

    Joined:
    Feb 7, 2017
    Posts:
    32
    You can set position manually in Update(), using Rigidbody.Moveposition or Transform.Translate, to simulate velocity. At high speed, this means you set the bullet to multiple positions within a single update call and raycast multiple times to check for collision. This is expensive so it's best for low rate-of-fire sniper rifles and such.

    Collider detection and one single raycast will not work at very high velocity. The position of the object seems to be interpreted based on velocity, which means a high velocity object may have its positions changed by several meters between each frame, leading to the object skipping an intended target/position. One raycast may work at moderately high velocity, but if the object's position changes by a huge distance between frame then the raycast distance still cannot reach the last/next point.
     
    Last edited: Mar 7, 2021
    Zullar likes this.