[tl;dr]
After a certain velocity speed, collision detection seems very accurate (specifically continuous dynamic, discrete seems to always be bad), however, under a certain velocity speed (slow, generic speeds), there is interpenetration (poor collision detection). Why is this? How to avoid?
[/tl;dr]
EDIT - From further testing, it seems that discrete pretty much always gives bad collision detection, and continuous dynamic only gives good collision detection after a certain velocity. Perhaps this is for performance reasons, though, If that is the case, I would like an option to have it work constantly.
I would like to ask the developers at unity if there are certain conditions for collision detection to start kicking into high gear (specifically continuous dynamic collision detection), and if so, how to disable it. It would seem very possible for optimizing and performance reasons.
What I mean is, after doing some tests it seems that at low, generic speeds a rigidbody would somewhat penetrate other objects (lower speeds for mesh colliders compared to primitive colliders(or at least for a cube)).
If the rigidbody is going past a certain speed, it will no longer interpenetrate other objects, and will continuous dynamic on, it will handle very high speeds. This seems true whether you are using addforce or changing the velocity directly, although it seems if you have the velocity stay constant then it doesnt interpenetrate.
EDIT - To test yourself, follow this…
Click for testing yourself
For you to test this… create a new scene.
1 - Put your fixedTimestep to .01 and min penetration/default contact offset to .01
2 -Create 2 cubes and put that at the origin (0,0,0)…
One cube gets a mesh collider (mesh colliders give better results from my tests). Set this mesh collider cube 10 units in the z axis.
The other cube, add this script on it.
Click for code
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Rigidbody))]
public class TestInterpenetration : MonoBehaviour
{
public bool interpenetrate = true;
Rigidbody myRigidbody;
Vector3 startPosition;
void Start()
{
myRigidbody = gameObject.GetComponent<Rigidbody>();
myRigidbody.useGravity = false;
myRigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
myRigidbody.constraints = RigidbodyConstraints.FreezeRotation;
startPosition = transform.position;
StartCoroutine(GoBack());
}
void FixedUpdate()
{
if(interpenetrate) myRigidbody.AddForce(transform.forward * 50);
if(!interpenetrate) myRigidbody.AddForce(transform.forward * 100);
CheckInterpenetration();
}
void CheckInterpenetration()
{
RaycastHit[] hitInfos;
hitInfos = Physics.RaycastAll(transform.position + ((transform.forward * .49f) + (-transform.right * 2)), transform.right, 5);
if(hitInfos.Length == 0) return;
foreach(RaycastHit hitInfo in hitInfos)
{
if(hitInfo.collider && hitInfo.collider.transform != transform)
{
Debug.DrawRay(transform.position + ((transform.forward * .5f) + (-transform.right * 2)), transform.up * 10, Color.red, .5f);
Debug.Log("Interpenetrated");
}
}
}
IEnumerator GoBack()
{
while(true)
{
myRigidbody.velocity = Vector3.zero;
transform.position = startPosition;
yield return new WaitForSeconds(2);
}
}
}
3 - Press play. Notice in the inspector there is a checkbox for “Interpenetration”. It is by default set to true. You should see red lines appearing when the boxes collide. If so, this means there was an interpenetration. Uncheck this box and you will notice the box moves faster, but there should be no more red lines, meaning collision is being handled properly. All this checkbox is doing is changing the force from 50 to 100.
I am trying to find out why this is happening.
If you try this out and you don’t get the same results as I do, let me know what unity version you are using. I am using 5.0.2f1
For example.
If I take cube, make it a rigidbody with no gravity and rotations locked, collision detection mode is at continuous dynamic and put it at 0,0,0 (with collision detection discrete, it seems to always be bad until it just completely goes through)
Take another cube with a box collider (no rigidbody) and put it at 0,0,10 (10 in z).
- I use this for the rigidbody “myRigidbody.velocity += (Vector3.forward * 2.993);”
- I press play and watch the rigidbody interpenetrate the other box and then snap back.
- Now I change the value “2.993” to “2.994” or higher and it will no longer interpenetrate, no mater what number I tried above “2.993” it didn’t interpenetrate. If I move my box from 0,0,10 to something else then the numbers would need to be different, but its the same case. It gets to a point to where after a certain number, it will no longer interpenetrate.
(Note - this may not be the case for others since physics may act a bit different on everyones computers) - If I add a mesh collider instead of a box collider to the non rigidbody, then if the value is at “0.781” or lower it interpenetrates, but at “0.782” or higher it doesnt.
If I use AddRelativeForce then at value “78.125” or lower it interpenetrates, but at “78.126” or higher it doesn’t.
EDIT - I noticed that if I go as low as .5 force, it wont interpenetrate, but at 1 it would. It might be inconsistent at lower velocities, but at higher it seems consistent (though of course I didn’t test every value)
My timestep is at .01, and my physics default contact offset at .01, solver iteration at 6
I am also using unity 5.02f1 in case that matters.
Here is what I am seeing.
The red line indicates an interpenetration happened.
What I want to know if there is something being done behind the scene for performance reasons to make the rigidbody have bad collision detection unless velocities are met, and if so, can we have a checkbox somewhere on the rigidbodies to remove the bad collision detection even if there is a drop in performance. I pretty much cannot use rigidbodies as it looks disgusting when it just goes inside walls for a few frames, at such low speeds, and to do a bunch of things to fight this is a pain.
There also might be a bug in that a rigidbody that is in continuous dynamic mode before pressing play, press play, and then turned to discrete will seemingly act like its still on continuous dynamic as it wont go through things when moving really fast, compared to starting in discrete mode where it now is going through things.