Just posting this here because I had been assuming otherwise.
When 2 objects collide, inside OnCollisionEnter() or OnCollisionStay() you can use Collision.contacts[0].point to get the location of the first contact point. There is always guaranteed to be at least one.
I’m moving a rigidbody sphere collider against a stationary mesh collider. The sphere is using a script which simply moves it forward and draws a line at any contact point detected. It uses a physics material with bounce and friction zeroed out.
I had been assuming that since one of the colliders is stationary, the collision point would never fail to be on that collider’s surface.
Here’s the scene:
Most of the time, it is exactly as expected. The collision point is on the non-moving surface. But letting the sphere run back and forth a few times, I get this:

Earlier, coming down very fast from the right, one rather large difference:

And moving horizontally only (this surprised me):

Here’s the script:
using UnityEngine;
using System.Collections;
public class Move : MonoBehaviour
{
void FixedUpdate()
{
rigidbody.AddForce(transform.forward * 20.0f);
}
void OnCollisionEnter(Collision enterColl)
{
Debug.DrawRay(enterColl.contacts[0].point, Vector3.up, Color.blue, 10.0f);
}
void OnCollisionStay(Collision stayColl)
{
Debug.DrawRay(stayColl.contacts[0].point, Vector3.up, Color.white, 10.0f);
}
}
It gives the appearance that the contact point is always going to be a point on the moving object, not the surface. It doesn’t matter which object called OnCollisionStay(), as I ran a similar script on the surface mesh, using red lines instead, and the results didn’t change.
Playing with settings showed that Min Penetration For Penalty doesn’t have any effect on this, but Solver Iteration Count does. That makes sense, however not quite as much as I’d like. Setting Solver Iteration Count to 100 still gives the same discrepancy on the horizontal part of my test. Why?
Setting it to just 1 still gives contact points that are perfectly flush with the stationary surface for the large majority of collisions.
So in conclusion it appears that Collision.contacts[ ].point is a point that is guaranteed to be on the moving body’s surface, but not the stationary object’s surface. What precisely defines that point, I don’t know.


