Inconsistent Collision Detection

Greetings,

I’ve encountered a simple problem with collision detection. I have a target (a spaceship in this case) and a bullet. Both are rigidbodies and both have primitive colliders. The bullet is given an initial push, accelerating it to a moderately high velocity towards the target. Sometimes the bullet hits the target and physics appropriately take place. Sometimes there is no collision at all and the bullet continues on it’s merry way.

The real problem is that this happens even if both objects are set to be any combination of Continuous or Continuous Dynamic collision detection. The problem is worst under Discrete collision detection, but the rate of failure is still completely unacceptable even if both bullet and target are set to use Continuous Dynamic collision detection.

I’ve tried adding multiple layers of primitive colliders to the target, which helps “catch” the bullets, but that still looks terrible when bullets often impact inside the model rather than on/near the surface (or even worse, impact the opposite side as they exit). I’ve tried using mesh colliders, with even worse results (and far worse performance). The velocity involved really isn’t that high compared to the size of the target, so this is a substantial obstacle from a design standpoint.

The question is: what else can I do to improve the consistency of my collision detection?

Also check that your Fixed Timestep (under Project Settings > Time) is set to a pretty small value. We were using 0.03 for awhile, but ran into a lot of physics issues. Setting this to like 0.01 made physics behave better for the most part, at the cost of some performance.

I approached this in a mixed way since I needed bullet drop. In the script attached to the bullet, I checked at start and in every frame what the distance was to the target using raycast. If the distance was less than the bullet velocity * deltaTime * 2 (2 is just to make sure, but can be varied), then I hit the raycast collider gameobject. Not perfect, but better than just raycast or monkeying with Physic settings. Code:

using UnityEngine;

public class Bullet : MonoBehaviour
{
    public float BulletLife = 5;
    private float _currentLife = 0;
    private RaycastHit _hitInfo;
    private const float CHECK_MULTIPLIER = 2f;
    // Use this for initialization
    private void Start()
    {
        if (IsCloseToTarget()) RegisterHit();
    }

    private void FixedUpdate()
    {
        _currentLife += Time.deltaTime;
        if (_currentLife > BulletLife) Destroy(this.gameObject);

        if (IsCloseToTarget()) RegisterHit();
    }

    private bool IsCloseToTarget()
    {
        Physics.Raycast(transform.position, this.gameObject.rigidbody.velocity.normalized, out _hitInfo);
        if (_hitInfo.collider != null && _hitInfo.collider.gameObject != null)
        {
            //Debug.Log("Bullet Distance:" + _hitInfo.collider.gameObject.name + "|" + _hitInfo.distance.ToString() + "|" +
            //          gameObject.rigidbody.velocity.ToString() + "|" + Time.deltaTime.ToString());
            var distChk = gameObject.rigidbody.velocity.magnitude * Time.deltaTime * CHECK_MULTIPLIER;
            return _hitInfo.distance < distChk;
        }
        return false;
    }

    private void RegisterHit()
    {
        Debug.Log("Bullet Hit " + _hitInfo.collider.gameObject.name);
        Destroy(this.gameObject);
    }
}

The problem you’re having is that movement in games isn’t continuous. You’re teleporting the bullet forward frame by frame, making it look like it’s moving. If it’s moving to fast though, it might go past an object without collision taking place.

There are several ways to prevent this. the easiest way is using this script, DontGoThroughThings.js, which basically checks where am I now, where will I be next frame, and will I have skipped over something then?