- Home /
Anyway to tell which side of a collider is hit?
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?
Answer by rutter · Sep 05, 2014 at 10:11 PM
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.
That's an amazing answer. I was thinking you'd have to get the location position on the collider of the raycast hit but I had no idea how to do that. This is absurdly helpful
But in this specific case, would it just be better to make one collider for the chest and one collider for the back?
I enjoy $$anonymous$$ching, when I can. :)
If you can swing the two-colliders thing, it's probably easier and quicker, with the added benefit that your code doesn't need to know what kind of collider it is, just which one it is (you could check the name, set inspector values to compare against, or whatever).
Alright, I'll try both options. $$anonymous$$nowing how to deter$$anonymous$$e where on a collider there's a hit seems to be very helpful for other things, though. Thanks so much for explaining
Sorry for necroposting, but this was the first search result for me, and while it's really super helpful answer, I found out an easier way instead of using dot products. Also, I got issues with the dots method when the hit point is close to the collider edges.
So, we can get a side from the localPoint
itself.
If the hit point is at front or rear side of the collider, then localPoint.z
is always 0.5
or -0.5
.
If we hit a left/right side, then localPoint.x
is always 0.5
or -0.5
. And if we hit upper or bottom side, localPoint.y
is always 0.5
or -0.5
.
The overall code will look like this:Vector3 localPoint = hit.transform.InverseTransformPoint(hit.point); if ($$anonymous$$athf.Abs(localPoint.x) == 0.5f) Debug.Log("Right/left"); else if ($$anonymous$$athf.Abs(localPoint.y) == 0.5f) Debug.Log("Top/bottom"); else if ($$anonymous$$athf.Abs(localPoint.z) == 0.5f) Debug.Log("Front/rear");
Answer by svitlana · Feb 20, 2016 at 06:29 AM
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");
}
}
How would you suggest to detect the touch on a sphere collider where the touch should not have passed through an game object?
So for example you touch the front of a game object and this touch passes through to the sphere collider on the rear of the game object and the trigger fires?
Answer by jtagrawal2000 · Oct 09, 2020 at 07:16 AM
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”);
}
Answer by tkamruzzaman · Jul 20, 2016 at 09:06 AM
this may help: http://answers.unity3d.com/questions/339532/how-can-i-detect-which-side-of-a-box-i-collided-wi.html
Your answer
![](https://koobas.hobune.stream/wayback/20220613162406im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Raycast is not hitting a box collider? 1 Answer
Creating a working meshcollider in code 3 Answers
How can I make diagonal collisions work with raycasts from a boxcollider? (3D, C#) 0 Answers
Player have to stop when hit a corner 0 Answers
A script that auto generated the box collider around a 3d model 3 Answers