Collision detected outside of the object

I have a fast moving object that should detect collision with the rectangular in the centre (a blast is seen). If the rectangular is not touched, no collision should be detected. The ball has a Rigidbody with collision detection of Continuous Dynamic. The rectangular and the wall have a Rigidbody with Continuous detection. I am using the following code:

private void OnCollisionEnter(Collision collision)
{
        GetComponent<TrailRenderer>().enabled = false;

        if (collision.collider.tag == "Enemy")
        {
            GameObject expl = Instantiate(explosion, transform.position, Quaternion.identity) as GameObject;
            Destroy(expl, 2);
        }
}

The problem is that the collision is detected even when the ball hits the wall close to the rectangular. If it hits the wall far from the object, the collision is not detected (as it should). Based on what I have researched so far, the collision detection is not perfect with fast moving objects even when continuous detection is used. Is there any way to address this issue?

Here is the video:

Thanks!

Can you show the inspector?

Attached. Thank you!

7509334--925819--ball_1.png
7509334--925820--enemy_1.png
7509334--925823--wall_1.png

I think that the error is in the enemy, it is in the water layer. Not sure, but I know the water layer has some specific attributes.
Change it to another layer
Also, if the wall doesnt move, it doesnt need a rigidbody.

Thanks, @r31o , for the suggestion. Unfortunately, it does not help. Tried different layers, but still having the same problem.

Also, it may be a placebo, but it looks like the faster the ball flies, the greater the distance is outside of the enemy boundary where collision is detected.

I think maby will be CCC (continous collision detection), as it tries to predict where the ball will be, so, for the physics engine, “Is there” even if physicaly isint.
Just try it. Maby it can solve your problem.
If not (I hope that I solved the problem), put it here and I will try to figure out what happens. :stuck_out_tongue:

You could try ray casting the collider from it’s origin to destination. This obviously only works for linear movement, but it’s about as reliable as it gets. In my case I have objects that can reach 20 unity-units-per-second speed and this approach never betrayed me so far.

The video you demonstrated kinda looks too wrong to be true. CCD has its’ issues, but it’s not this inaccurate. We can’t help based on the provided information, but I suspect there is some error in your scene setup that you’re missing, that makes this behaviour perfectly valid.

Like for example your slingshot stone has a spherical model but you use a box collider for it? Visually the ball may not be touching the ‘enemy’, but the invisible box that you’re using for collision detection probably is.

You can investigate your problem by inserting a Debug.Break() call when the ‘explosion’ is spawned. Debug.Break() is the same as pressing pause in the editor. When the pause occurs, switch to the scene view and take a close look at the state of the scene and the hit boxes. Maybe even take a look at the physics debug view https://docs.unity3d.com/Manual/PhysicsDebugVisualization.html

Thank you, @BakeMyCake . I have tried playing with Debug.Break(), and the results are attached. Here is a more complete script for the stone prefab:

public class Stone : MonoBehaviour
{
    public Vector3 initPosition;
    public Rigidbody Rb;
    public GameObject explosion;
    public float ReleaseTime = 0.1f;
    public float DestructionTime = 2.0f;
    private bool _isPressed;
    private bool _isFired;
    public float RbForceFactor = 2000;


    private void Awake()
    {
        initPosition = transform.position;
        Rb = GetComponent<Rigidbody>();
    }


    void FixedUpdate()
    {
        if (_isPressed && !_isFired && !GameManager.Instance.IsLevelCleared)
        {
            Vector3 mousePosition = Input.mousePosition;

            // Factors that affect the extent to which stone can be moved to the sides (depends on the resolution?)
            float screenToWorldPoint_factor = 1f;
     
            // Stone is moved along the z-axis depending on moving the mouse along the Y-axis
            float x2 = .... here goes a formula
            float x1 = .... here goes a formula
            float y2 = .... here goes a value
            float y1 = .... here goes a value
            float m = (y2 - y1) / (x2 - x1);
            float b = .... here goes a value
            float worldPosition_z = m * mousePosition.y - b;

            Vector3 worldPosition = Camera.main.ScreenToWorldPoint(new Vector3( mousePosition.x,
                                                                                screenToWorldPoint_factor,
                                                                                screenToWorldPoint_factor));

            worldPosition.y = 3.3f;
            worldPosition.z = worldPosition_z;

            Rb.position = worldPosition;
        }
    }


    void OnMouseDown()
    {
        if (_isFired || GameManager.Instance.IsLevelCleared)
        {
            return;
        }

        _isPressed = true;
        Rb.isKinematic = true;
    }


    void OnMouseUp()
    {
        if (_isFired || GameManager.Instance.IsLevelCleared)
        {
            return;
        }

        _isPressed = false;
        Rb.isKinematic = false;

        // Rigidbody Force
        // Y-position of the initial position should equal Y-position of the transform position
        // Otherwise, the stone will be flying higher
        initPosition.y = transform.position.y;

        Vector3 directionToInitialPosition = initPosition - transform.position;
        Rb.AddForce(directionToInitialPosition * RbForceFactor);

        Destroy(GetComponent<SpringJoint>());

        GetComponent<TrailRenderer>().enabled = true;
        _isFired = true;
        StartCoroutine(Release());
    }


    private void OnCollisionEnter(Collision collision)
    {
        GetComponent<TrailRenderer>().enabled = false;

        Debug.Log("Collider: " + collision.collider.name);

        // Explode on collision with the Enemy
        if (collision.collider.tag == "Enemy")
        {
            Debug.Break();
            GameObject expl = Instantiate(explosion, transform.position, Quaternion.identity) as GameObject;
            Destroy(expl, 2); // delete the explosion after 2 seconds
        }
    
    }


    IEnumerator Release()
    {
        yield return new WaitForSeconds(ReleaseTime);
        StartCoroutine(Explode());
    }


    IEnumerator Explode()
    {
        yield return new WaitForSeconds(DestructionTime);

        GameManager.Instance.SetNewStone();
        Destroy(gameObject);
    }
}

Thanks!

EDIT: All the research I have done does refer me to collision ray casting. I am Googling now for the best way to implement it.


While I am figuring how to do collision ray casting, I also wanted to show the video where the collision is happening frame by frame. This shows that collision is detected way outside of the applicable object.

I’ve attempted to recreate this but couldn’t in version 2020.3.6.
If you wanna try it out I’ve attached my test scene, make sure you set the physics layers so that the balls don’t collide with each other.

For me it looks like in the gif below:
Gif

7521680--928076--Collision2.gif

I don’t know what else to suggest other than maybe start checking every single setting you have to see what breaks it.

7521680–928073–collision2.unitypackage (8.73 KB)

Thank you so much, @BakeMyCake ! I will try it and report on the outcome.

@BakeMyCake and @r31o .

I believe I have found the culprit. It is in this code:

void OnMouseDown()
{
        if (_isFired || GameManager.Instance.IsLevelCleared)
        {
            return;
        }

        _isPressed = true;
        //Rb.isKinematic = true; THIS IS THE CULPRIT!!!
}

For me to be able to pull the stone imitating a slingshot, I was trying to make the ball’s rigidbody kinematic. If I remove this line, collision is detected properly. But in this case, I cannot pull the stone – it jitters then. If I keep the line, problems with collision occur.

In my opinion, this does not make any sense. Could anyone please explain why this may be even happening and how I could address it?

Thanks a lot!

1 Like

I don’t know if your project and error still persist but i think i found both problem and solution. I am writing for people who have same problem and googleing. For me the solution was: Go to: Edit > Project Settings > Physics and check the Default Contact Offset if the number there is 1 or greater change it to a lower value. I think it is in meters so something like 0.01 (1cm) should be fine.