Help with Quaternion.LookRotation

Hey guys. I have a little buglike creature that crawls across the ground. When it hits a hill I want it to point up the slope so that it climbs up instead of trying to go through the hill. To that end, I’m trying to use Quaternion.LookRotation towards the destination (target - currentLocation), using the ground normal as the “up” vector. Is However, my guy doesn’t ever seem to rotate to face up slope, even when the ground normal changes. Am I using Quaternion.LookRotation wrong, or is there something else wrong with my code? Here’s how I’m doing it:

	//get ground normal
	var groundHitHead : RaycastHit;
	var groundNormal : Vector3;
	if (Physics.Raycast(transform.position, -Vector3.up, groundHitHead)) { //raycast down, find normal
		groundNormal = groundHitHead.normal;
	}
	else { 
		Debug.Log("Error - terrain raycast hit nothing");
		return false;
	}

        //now rotate
	var rotation = Quaternion.LookRotation(finalTarget-transform.position, groundNormal); 		   
        transform.rotation = rotation;

You are close, but you dont need the look rotation at all.

Consider simply setting the ground normal as the up vector of the transform, but only after you retain the y rotation of the bug. Reapply the y rotation and you have it.

	//get ground normal
	var groundHitHead : RaycastHit;
	if (Physics.Raycast(transform.position, -Vector3.up, groundHitHead)) { //raycast down, find normal
		var y = transform.localEulerAngles.y;
		transform.position = groundHitHead.point;
		transform.up = groundHitHead.normal;
		var euler = transform.localEulerAngles;
		euler.y = y;
		transform.localEulerAngles = euler;
	} else { 
		Debug.Log("Error - terrain raycast hit nothing");
		return false;
	}

Okay, I’ll try this - but how does it point towards the intended target if it never uses the finalTarget value? (That was the original reason for the LookRotation.)

Do you want the X and Y rotation to look towards the target, or just the Y?

This means, if he could be facing, looking at the ground if the target is below, or the sky if the target is above.

You can do this one of two ways:

Set a lookat, towards the target, then use the script that I provided. This will give you what you are looking for fairly easy.

or

Use the raycast.normal as an up vector in the LookAt towards the target. you would then simply add euler.x = 0 to the code after doing the LookAt.

Below are both implemented:

	var groundHitHead : RaycastHit;
	transform.LookAt(finalTarget);
	if (Physics.Raycast(transform.position, -Vector3.up, groundHitHead)) { //raycast down, find normal
		var y = transform.localEulerAngles.y;
		transform.position = groundHitHead.point;
		transform.up = groundHitHead.normal;
		var euler = transform.localEulerAngles;
		euler.y = y;
		transform.localEulerAngles = euler;
	} else { 
		Debug.Log("Error - terrain raycast hit nothing");
		return false;
	}
	var groundHitHead : RaycastHit;
	if (Physics.Raycast(transform.position, -Vector3.up, groundHitHead)) { //raycast down, find normal
		var y = transform.localEulerAngles.y;
		transform.position = groundHitHead.point;
		//transform.up = groundHitHead.normal;
		transform.LookAt(finalTarget, groundHitHead.normal);
		var euler = transform.localEulerAngles;
		euler.x = 0;
		euler.y = y;
		transform.localEulerAngles = euler;
	} else { 
		Debug.Log("Error - terrain raycast hit nothing");
		return false;
	}

Thank you so much, I’m pretty sure this is almost what I need, but one more question, if I can - how can I do this so that I don’t implement changes in position and rotation right away? I’d like to get the ultimate rotation that I need, but apply it gradually with a Slerp later. So instead of just applying this rotation, can I just get the resulting Quaternion from it somehow?

EDIT: Actually, having tried this out now, it’s not working for me. I’m pretty sure (although not certain) it’s because the transform.position change is embedding the creature in the terrain, making it difficult or impossible for him to move forward. Even more so now, is there a way of doing this code without having it directly implement the change in the creature’s position or rotation? (For the record, “headPoint” is a point in the center of the creature’s forward head position. There is also a corresponding “tailPoint” at the back of the creature, but at the moment I’m not using it.)

cheat…

rotation = transform.rotation
transform.lookat(new position)
transform.rotation = Quaternion.Slerp(rotation, transform.rotation, damper * Time.deltaTime)

lol

It sounds like your making this way more complicated than it needs to be. :wink:

Holy crap, glad I read this thread randomly. So, instead of LookAt not working because the transform is several levels deep in the scene graph and things above it are moving in the same frame (not sure why this is a problem, but it sure isn’t working), I can just set the forward vector and Unity does the rest behind the scenes? This is great!

Hey Unity guys, could you maybe hint that this is possible somewhere in your documentation? Even at $1500/seat, some of that has to go towards documentation beyond a 1st/3rd person platformer tutorial. The Transform.forward documentation is especially not so great.

You are totally correct, someone turned me on to this idea a while back and it is the greatest thing ever.

Mind you it mimics the “LookAt” but forces the up vector to zero in that case. Like in the case of what Kagedtiger has, we had to reset the y rotation to maintain looking.

My question about this is quite simple.

→ Why LookRotation( direction, normal); don’t work?? !!! that’s in API :o

When i use LookRotation( direction, Vector3.right); it works, my transform has his head upward to the right.

However when i use LookRotation( direction, normal); my transform gets aligned upward with Vector3.up and NOT the normal of the slope going down…

What’s wrong? :o