I try to rotate object according normal rotation of terrain. More over this object should move. And I need to combine z and x from normal of terrain and y which rotates to target. I tried this but result is quiet weird:
You’re having weird results because you’ve messed with the components of a Quaternion - despite their names, they have nothing to do with the axes x, y and z.
If you want the character to keep looking to newPos direction while following the surface normal, you can use LookRotation(newPos, normal) - the second parameter indicates the up direction. About the surface normal: it’s better to keep a curNormal variable and Lerp it to the surface normal (or Vector3.up, if no terrain hit) to smooth the character orientation:
var curNormal = Vector3.up;
function getTerrainRot(myTarget:Vector3,terrPos: Vector3): Quaternion; {
var terrHit: RaycastHit;
var newPos: Vector3;
var normal = Vector3.up;
if(Physics.Raycast (terrPos, -curNormal, terrHit, 10.0)){
normal = terrHit.normal;
}
curNormal = Vector3.Lerp(curNormal, normal, 2*Time.deltaTime);
newPos = getPosAndTerrainY(myTarget) - terrPos;
return Quaternion.LookRotation(newPos, curNormal);
}
EDITED: You’re right: LookRotation in this case doesn’t work as expected - it prefers to look at the target direction and completely ignores the normal!
Let’s go back to the basics: calculate a rotation from Vector3.up to curNormal (as you already did), than multiply by the horizontal rotation from Vector3.forward to the target direction (multiplication in the Quaternion world actually combines the rotations):
var curNormal = Vector3.up;
function getTerrainRot(myTarget:Vector3,terrPos: Vector3): Quaternion {
var terrHit: RaycastHit;
var newPos: Vector3;
var normal = Vector3.up; // default normal = up
if (Physics.Raycast (terrPos, -curNormal, terrHit, 10.0)){
normal = terrHit.normal; // use the surface normal, if any
} // smoothly follow the surface normal
curNormal = Vector3.Lerp(curNormal, normal, 2*Time.deltaTime);
newPos = myTarget - terrPos; // get the direction to look at
newPos.y = 0; // zero y to keep only the horizontal direction
// calculate rotation to normal
var rot = Quaternion.FromToRotation(Vector3.up, curNormal);
// combine with the horizontal rotation
rot = rot * Quaternion.FromToRotation(Vector3.forward, newPos);
return rot;
}
When are you writing us a 'Quaternions for Unity developers' blog Al?
The problem is that LookAt really prefers to look at the target, completely ignoring the normal. I edited my answer to do things in the traditional quaternion way.
When are you writing us a 'Quaternions for Unity developers' blog Al?
– MeltdownNot work (. See here: http://img194.imageshack.us/img194/9264/movement.jpg
– 2dkotI'll check this script and return asap.
– aldonalettoThe problem is that LookAt really prefers to look at the target, completely ignoring the normal. I edited my answer to do things in the traditional quaternion way.
– aldonaletto@Meltdown, that's a tempting idea - but I still have to learn a lot of secrets of these four headed monsters before doing that!
– aldonaletto