- Home /
How to determine which side of an object the player collided with?
I have been using a combination of ray casts coming from the player and dots to tell which side of a cube the player is against. I do not need how much to the right or how far forward the player is all I need is whether they are on the right, left, front, or back side of the cube. I've been using this code and had been working pretty well.
wall = hit.transform;
Vector3 hitLoc = wall.InverseTransformPoint(hit.point);
Vector3 hitDir = hitLoc.normalized;
dotF = Vector3.Dot(wall.TransformDirection(Vector3.forward).normalized, hitDir);
dotR = Vector3.Dot(wall.TransformDirection(Vector3.right).normalized, hitDir);
if (Mathf.Abs(dotF) > Mathf.Abs(dotR))
{
dotR = 0.0f;
if (dotF > 0)
{
dotF = 1.0f;
}
else if (dotF < 0)
{
dotF = -1.0f;
}
}
if (Mathf.Abs(dotR) > Mathf.Abs(dotF))
{
dotF = 0.0f;
if (dotR > 0)
{
dotR = 1.0f;
}
else if (dotR < 0)
{
dotR = -1.0f;
}
}
However once I started using cubes that were rotated I started having problems. Anytime the player nears the edges of the cubes it will switch to say that it is on another side.
Example: If the player is on the front side of a cube that is rotated 165 on the y axis and moves toward the edge then it suddenly says the player is on the right side.
I'm no expert when it comes to this kind of stuff, and can't figure out how to make it work. Maybe dots were the wrong way to go. As long as I can tell which side of the cube the player is against I don't care what method is used, so any suggestions are welcome. Thanks.
Answer by unity_ek98vnTRplGj8Q · Feb 04, 2020 at 04:28 AM
Maybe there is a better way to do this, but my first instinct would also be to use the dot product. I do notice a couple big mistakes in your code however. Don't use InverseTransformDirection on hit.point. If you want to get the direction of the hit from the center of the object use hit.point - hit.transform.position. My code would look something like this (I have not tested this code)
Vector3 hitDirection = hit.point - hit.transform.position;
//Dot products
float upWeight = Vector3.Dot(hitDirection, hit.transform.up);
float forwardWeight = Vector3.Dot(hitDirection, hit.transform.forward);
float rightWeight = Vector3.Dot(hitDirection, hit.transform.right);
//We care about the absolute value only for now
float upMag = Mathf.Abs(upWeight);
float forwardMag = Mathf.Abs(forwardWeight);
float rightMag = Mathf.Abs(rightWeight);
if(upMag >= forwardMag && upMag >= rightMag){
if(upWeight > 0) //Up
else //Down
}
else if(forwardMag >= upMag && forwardMag >= rightMag){
if(forwardWeight > 0) //Forward
else //Back
}
else{
if(rightWeight > 0) //Right
else //Left
}
Thanks for the help. That wasn't the problem, but I'm sure it would have become one later.
If anyone is wondering the problem was just that I had four ray casts one for each direction going out from the player. Whenever the player was at an angle two of them would touch the cube at once, so whenever the player approached the edge one would go off the edge and hit something else. It didn't always hit something else which was why the problem was so inconsistent.
Answer by haseeb5639 · Feb 04, 2020 at 05:25 AM
Use four colliders on 4 different sides. Give them 4 different tags. SIMPLE!
I mean you're technically right that would easily solve my problem. However, it might be a bit of a hassle to work with multiple colliders every time I have to make a cube or change the dimensions of one. Thanks for the idea though and it'll be good to have in case I can't find a solution that works with just a single cube.
Your answer
Follow this Question
Related Questions
Cylinder Ground Collision 0 Answers
Problem with using Ray Casting to avoid obstacles and walls.. 1 Answer
Adding a raycast to prevent camera from going through walls? 0 Answers
How to add platform motion to player controller without parenting? - Mostly working code 1 Answer
Raycast for 2d with touch. 0 Answers