I would like to rotate an object to match its ground. So i cast 3 Rays (at the corners) to calculate the normal of the plane below.
Now i need to rotate the object accordingly but keep the y rotation (so in which direction it "faces") so just setting transform.up = normal
does not work.
I thought i could just use the dot product between the transform directions to rotate it (so xRotation = Vector3.Dot(normal, transform.forward)
for x and zRotation = Vector3.Dot(normal, transform.right)
for z) this should be the angles between the normal vector and the right/forward vector. But as the result my object just faces the sky that way to the idea is completely wrong.
Do you know how i should proceed ?
CodePudding user response:
Here is the solution to your problem. Although there are different methods for doing this, I personally find it best to use the Cross
axis. In fact, you need Vector3.Cross
instead of Vector3.Dot
. This code works in such a way that by multiplying the transform.right
of the player on the Ground normal vector, Since this axis calculates the perpendicular direction, you can expect it to give a forward corresponding to the ground.
public LayerMask groundLayer; // The Layer Ground
public Vector3 offset = Vector3.up;
private void Update()
{
if (Physics.Raycast(transform.position, Vector3.down, out var groundHit, 2f, groundLayer.value))
{
var cross = Vector3.Cross(transform.right, groundHit.normal);
var _lookRotation = Quaternion.LookRotation(cross, groundHit.normal);
transform.position = groundHit.point offset; // the offset is OPTIONAL, you can adjust it manuel or remove
transform.rotation = _lookRotation;
}
}
Result:
You can see the result below. Consider that you can delete the offset code and make it compatible with the ground with mechanisms such as CharacterController
or Rigidbody
.