How to prevent colliders from passing through each other?

114,379

Solution 1

Collision with fast-moving objects is always a problem. A good way to ensure that you detect all collision is to use Raycasting instead of relying on the physics simulation. This works well for bullets or small objects, but will not produce good results for large objects. http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html

Pseudo-codeish (I don't have code-completion here and a poor memory):

void FixedUpdate()
{
    Vector3 direction = new Vector3(transform.position - lastPosition);
    Ray ray = new Ray(lastPosition, direction);
    RaycastHit hit;
    if (Physics.Raycast(ray, hit, direction.magnitude))
    {
        // Do something if hit
    }

    this.lastPosition = transform.position;
}

Solution 2

I have a pinball prototype that also gave me much trouble in the same areas. These are all the steps I've taken to almost (but not yet entirely) solve these problems:

For fast moving objects:

  • Set the rigidbody's Interpolate to 'Interpolate' (this does not affect the actual physics simulation, but updates the rendering of the object properly - use this only on important objects from a rendering point of view, like the player, or a pinball, but not for projectiles)

  • Set Collision Detection to Continuous Dynamic

  • Attach the script DontGoThroughThings (https://www.auto.tuwien.ac.at/wordpress/?p=260) to your object. This script cleverly uses the Raycasting solution I posted in my other answer to pull back offending objects to before the collision points.

In Edit -> Project Settings -> Physics:

  • Set Min Penetration for Penalty to a very low value. I've set mine to 0.001

  • Set Solver Iteration Count to a higher value. I've set mine to 50, but you can probably do ok with much less.

All that is going to have a penalty in performace, but that's unavoidable. The defaults values are soft on performance but are not really intented for proper simulation of small and fast-moving objects.

Solution 3

How about set the Collision Detection of rigidbody to Continuous or Continuous Dynamic?

http://unity3d.com/support/documentation/Components/class-Rigidbody.html

Solution 4

  • Edit ---> Project Settings ---> Time ... decrease "Fixed Timestep" value .. This will solve the problem but it can affect performance negatively.

  • Another solution is could be calculate the coordinates (for example, you have a ball and wall. Ball will hit to wall. So calculate coordinates of wall and set hitting process according these cordinates )

Solution 5

Old Question but maybe it helps someone.

Go to Project settings > Time and Try dividing the fixed timestep and maximum allowed timestep by two or by four.

I had the problem that my player was able to squeeze through openings smaller than the players collider and that solved it. It also helps with stopping fast moving objects.

Share:
114,379
CLo
Author by

CLo

Day job GitHub account: https://github.com/adsklowenthal

Updated on July 09, 2022

Comments

  • CLo
    CLo almost 2 years

    I am having trouble keeping game objects inside of a contained space. When they reach the edge, there is some momentary push back but then they will go right through the wall.

    I am using a Box Collider on the player, and a Mesh Collider for the level's wall. I am having issues with both a Player Character (a space ship) that the movement is controlled by the player. And with projectiles, which are fire and forget moving at a constant speed.

    This is my movement code for my player. It is being run in the FixedUpdate() function.

    //Movement
        haxis = Input.GetAxis("Horizontal") * speed;
        vaxis = Input.GetAxis("Vertical") * speed;
    
        moveVector.x = haxis;
        moveVector.z = vaxis;
    
        if(moveVector.magnitude > 1)
        {
            moveVector.Normalize();
        }
    
        rigidbody.MovePosition(transform.position + moveVector * speed);
    

    With the bullets, they are given a velocity and the engine calculates their moviements. They are using Box Collider and it is set as a Trigger so they don't have physics. But I use OnTriggerEnter to destroy them.

    //Projectiles without physics collisiions
    function OnTriggerEnter (other : Collider) {
        Destroy(gameObject);
    }
    

    Some, but not all of the bullets will be destroyed when hitting the mesh collider wall. The player will sometimes hit it and stop, but can usually push through it. How can I make the collisions with the mesh collider work every time?

  • CLo
    CLo over 12 years
    I'm pretty sure that mesh colliders can't be set to Continuous if they are more than a certain number of tris. And even so, setting Continuous / Continuous Dynamic on the characters / bullets and even the meshes didn't work.
  • CLo
    CLo over 12 years
    Submitted an edit, but it should be Ray(lastPosition, direction) otherwise you may be inside the mesh collider and the Ray won't hit from inside of a collider. Looks like a good approach, I'll check it out.
  • CLo
    CLo over 12 years
    The only problem I can think of here is that we could be looking at a lot of moving elements and I suspect doing Raycast on all of them will be heavier on performance than using the compound colliders. If I get a chance to test this out I'll let you know what the performance difference is.
  • Petrucio
    Petrucio over 12 years
    collider.Raycast checks against a single collider - I edited to Physics.Raycast. Regarding performance, I don't think it will have a big hit, but it needs testing. You cam use the layerMask parameter of Physics.Raycast to ensure it only gets tested against what you want it to (see the docs).
  • AlfredoVR
    AlfredoVR over 12 years
    Raycasting is the way to go, because a lot of theoretical stuff that i can't fit in a comment, but this is the answer.
  • CLo
    CLo over 12 years
    Thanks @Fabio'Petrucio'Stange this answers the question very well. Though further along with my project, I need the physics info from a collision (some complex obstacles that will actually hit/damage the player based on the collision data). For this the compound colliders are doing the job quite well, I don't expect the Raycast to give me as much data.
  • Crazy Developer
    Crazy Developer almost 11 years
    Hi, I am not able to find the DontGoThroughtThings scripte Can you provide it. may be user has remove from above link.
  • Crazy Developer
    Crazy Developer almost 11 years
    I found link for the DontGoThroughtThings Scripte code.google.com/p/lava-in-antarctica/source/browse/trunk/…
  • Kunalxigxag
    Kunalxigxag about 9 years
    Am using Unity 5 and after reading this, though I couldn't find 'Min Penetration for Penalty' but I tried changing the 'default contact offset' to 1. Now, fast moving objects are getting detected :)
  • Taranasus
    Taranasus over 8 years
    You sir, are my new God! THANK YOU!
  • nipponese
    nipponese over 6 years
    Collision Detection: Dynamic worked for me. Using Unity 2017.
  • Ramon Dias
    Ramon Dias over 3 years
    why not use mesh colliders?
  • Simran Singh
    Simran Singh over 3 years
    Mesh collider are hard to process, more mesh means more usage of processor, this questions is old so, at that time it was harder for mesh to process on cheap phones, specially android phones.
  • ghanbari
    ghanbari about 3 years
    You can use Rigidbody.maxDepenetrationVelocity for big objects that moving fast.
  • CLo
    CLo about 3 years
    @ghanbari might be worth writing up a new answer. This is a 5 year old question, so an updated answer would be helpful.