Say you have a box collider attached to a character’s bone tagged as “Chest”, which encompasses the entire torso. But you’d like to determine whether a raycast hit the front face of that collider or the back face of that collider, how would you go about determining that?
Truth be told, the easiest and best way to do this is by using multiple colliders. Check which collider you hit, and react based on that.
If you really must inspect the collision details, you can use an overload of raycast that populates RaycastHit data, including the point of impact.
I’ll assume we have this data populated by raycast call:
RaycastHit hit;
You said we have a BoxCollider?
BoxCollider box = hit.collider as BoxCollider;
if (box == null) Debug.LogWarning("Collider is not a BoxCollider!");
Let’s convert our collision point to local space:
Vector3 localPoint = hit.transform.InverseTransformPoint(hit.point);
Vector3 localDir = localPoint.normalized;
This gives us a point relative to the box collider itself.
Is the point above or below the box? To the right or the left? In front or behind? We can use dot products to find out.
float upDot = Vector3.Dot(localDir, Vector3.up);
float fwdDot = Vector3.Dot(localDir, Vector3.forward);
float rightDot = Vector3.Dot(localDir, Vector3.right);
In this example, the dot product tells us if two vectors are pointing in similar directions. You’ll get -1 if they’re pointing exactly opposite, 0 if they’re exactly perpendicular, or 1 if they’re exactly parallel.
Our point might be slightly above the box, and far to the right of it. These dot products tell us how far the point has moved in any of those three directions.
(In case you’re wondering, the value is equal to the sine of the angle between the two vectors.)
- If
upDot
is positive, we’re above the box; if negative, we’re below the box. - If
fwdDot
is positive, we’re in front of the box; if negative, we’re behind the box. - If
rightDot
is positive, we’re to the box’s right; if negative, we’re to its left.
We can find out which direction is pointing furthest by comparing their absolute value:
float upPower = Mathf.Abs(upDot);
float fwdPower = Mathf.Abs(fwdDot);
float rightPower = Mathf.Abs(rightDot);
- If
upPower
is the largest, we’re mostly above or below the box. - If
fwdPower
is the largest, we’re mostly in front of or behind the box. - If
rightPower
is the largest, we’re mostly to the left or right of the box.
Combine these two discoveries, and you’ll know which side of the box you hit.
private void OnTriggerEnter (Collider other)
{
Vector3 direction = other.transform.position - transform.position;
if (Vector3.Dot (transform.forward, direction) > 0) {
print ("Back");
}
if (Vector3.Dot (transform.forward, direction) < 0) {
print ("Front");
}
if (Vector3.Dot (transform.forward, direction) == 0) {
print ("Side");
}
}
Use this to look for direction of collision
If this is included in script of a object which collides with c then this will print which side of c did a hit , you can also look to see if it hit the corners by checking the direction’s values
void OnCollisionEnter(Collision c)
{
Vector2 direction = c.GetContact(0).normal;
If( direction.x == 1 ) print(“right”);
If( direction.x == -1 ) print(“left”);
If( direction.y == 1 ) print(“up”);
If( direction.y == -1 ) print(“down”);
}