- Home /
Raycast Normal in Local Rotation?
I'm trying to align the local x axis of an object (p) to a raycast normal from the parent object. However I ran into a ton of problems. I finally got it to work but I realized the normal direction always somehow set the x axis as if the raycast had come from the world rotation and not the local rotation of the parent object. Is there something wrong with this code?
var bhit : RaycastHit;
var fhit : RaycastHit;
var bpos = transform.position - transform.forward * .4;
var fpos = transform.position + transform.forward * .4;
if (Physics.Raycast(bpos, -transform.up, bhit, 2, rotateMask))
{
if (Physics.Raycast(fpos, -transform.up, fhit, 2, rotateMask))
{
Debug.DrawLine(fpos, fhit.point);
Debug.DrawLine(bpos, bhit.point);
var averageHit = (fhit.normal + bhit.normal) / 2;
var hitRotation = Quaternion.FromToRotation(transform.up, averageHit);
if (fhit.point.y >= bhit.point.y)
p.transform.localRotation.x = Mathf.Lerp(p.transform.localRotation.x, hitRotation.x, Time.deltaTime * 3);
else
p.transform.localRotation.x = Mathf.Lerp(p.transform.localRotation.x, -hitRotation.x, Time.deltaTime * 3);
p.transform.localRotation.z = hitRotation.z;
//Debug.Log(hitRotation);
}
}
The reason for the hit.point check is because I thought I could negate the effect when it's goes the opposite direction, however I realized that's only because the raycast seems to cast in world space, in only one direction. Is there a way to cast in local space so that the normal can be used to calculate the proper local x axis?
You cannot assign individual components of a Queternion (i.e. localRotation) independently and expect anything. They are not angles. Also your fhit.normal and bhit.normal are in world space. I'm not sure what you are trying to align with what. If it is just the 'x' axis of the current object with the averageHit normal, you can do:
transform.rotation = Quaternion.FromToRotation(transform.up, averageHit) * transform.rotation;
Ah okay that seemed to work however it looks like I still need to check the hit.point.y to reverse the effect but I shouldn't have to do that if the normals can already tell the direction right?
I cannot tell you since I don't understand what you are trying to do (and that's why I put this as a comment rather than an answer). Depending on what you are doing, you may need to reverse the normal (i.e. use -averageHit).
I'm trying to rotate my character to the floor normal but only his local x axis because his parent is the one that is rotating along the y. However when I raycast down with the two raycasts above, and average them out, I get some really weird things, even with the modified code you suggested. For some reason even with the checks he rotates or doesn't rotate at all even though both normals are clearly pointing in a direction.
He's not rotating with the normals (red) using the code above :/
Answer by SomeGuy22 · Aug 03, 2013 at 03:54 AM
robertbu:
"This 'parent' and 'child' separate rotations has me confused. Are you trying to get the character to stand up? If so you should use transform.up instead of transform.right in the code I provided you. Usually if you want something to only align on a certain axis, the trick is to modify the normal before calculating the rotation. You would project the normal onto a plane. Since I'm having trouble visualizing this problem, I cannot say that is what is needed here. Here is the ProjectVectorOnPlane function borrowed from Math3d in the Wiki and translated into JS.
function ProjectVectorOnPlane(planeNormal : Vector3, vector : Vector3) : Vector3{
return vector - (Vector3.Dot(vector, planeNormal) * planeNormal);
}
You would use it like this:
averageHit = ProjectVectorOnPlane(transform.right, averageHit);
"
Still getting some artifacts but nothing too major. THis works fine