- Home /
Alternative to Quaternion.LookRotation() ?
I am using the following code to setup my rotations:
// Get direction of next waypoint
Vector3 direction = waypoints[currentWaypoint].position - transform.position;
// Check if we passed the current waypoint and get the next one if we did
if( transform.position.x > waypoints[currentWaypoint].position.x )
{
currentWaypoint++;
}
else
{
Quaternion newRotation = Quaternion.LookRotation( direction.normalized ); // Replace?
float yAngle = Mathf.LerpAngle( transform.eulerAngles.y,newRotation.eulerAngles.y - 90, rBody.velocity.magnitude * Time.deltaTime );
rigidbody.MoveRotation( Quaternion.Euler( 0, yAngle, transform.eulerAngles.z ));
}
As you can see I'm using 'Quaternion.LookRotation( direction.normalized )' to calculate the rotation towards the new target, but this only works on 'transform.forward' and my vehicle is moving on the x axis (transform.right) instead of the z axis, which is forward.
That's why i do 'newRotation.eulerAngles.y - 90' in the angle calculation. I would rather not do that, and I also don't want to child the vehicle to a parent which faces forward, so I was wondering if there is any alternative to Quaternion.LookRotation() that i can use, which doesn't force the rotation to the z axis?
Thanks for your time guys! Any help is greatly appreciated :)
Stephane
Answer by ronronmx · May 01, 2012 at 07:41 PM
Found the solution, here is an alternative to using Quaternion.LookRotation():
float turnAngle = Mathf.Atan2( direction.z, direction.x ) * Mathf.Rad2Deg;
float smoothAngle = Mathf.LerpAngle( transform.eulerAngles.y, -turnAngle, rBody.velocity.magnitude * Time.deltaTime );
rigidbody.MoveRotation( Quaternion.Euler( 0, smoothAngle, transform.eulerAngles.z ));
The Mathf.Atan2 function return an angle from 2 numbers (* Mathf.Rad2Deg is necessary to convert the angle to degrees), which is all I needed! Then I just create a smooth rotation from my vehicle's current y rotation to the new angle, and apply the results to "rigidbody.MoveRotation()".
Only thing I had to do for it to work correctly was to use '-turnAngle' instead of 'turnAngle' for the rotation to happen in the correct direction.
That's it! Maybe this will be helpful to others :)
Stephane
During my development, i needed like anybody else the alternative and customisable look at direction of the target rotation. here is a frontal look rotation. if you flip or rotate, the Object then add the modification. hope it helps.
public static float look_Angle ( Vector3 Distance_obj,Vector3 Position,Transform Object)
{
float Angle =0;
Vector3 Distance = Distance_obj;
float Self_rotate = Object.transform.rotation.eulerAngles.y;
float V = 0;
if (Distance.z > 0)
{
V = 180f;
float x = Distance.x;
float y = Distance.y;
float xy = Distance.x * Distance.y / $$anonymous$$athf.Sqrt(Distance.magnitude);
//for no rotation.
if (Distance.x > 0)
{
Angle = -(xy+V);//left cross
}
else if (Distance.x < 0)
{
Angle = -(xy-V);
}
}
if (Distance.z < 0)
{
float x = Distance.x;
float y = Distance.y;
float xy = Distance.x * Distance.y / $$anonymous$$athf.Sqrt(Distance.magnitude);
V = 0;
if (Distance.x >0)
{
Angle = xy+V;
}
else if(Distance.x < V){
Angle = xy+V;
}
}
return Angle;
}
Sorry but this method makes no sense at all. First of all it takes 3 parameters where you only use 1 effectively which is "Distance_obj". The other two are either not used at all or pointless. Specifically "Position" isn't used at all and "Object" is only used in this line:
float Self_rotate = Object.transform.rotation.eulerAngles.y;
Though "Self_rotate" in turn isn't used anywhere, so it's also pointless. The whole method could use some heavy refactoring. The local variables "x" and "y" are declared two times but aren't used at all. In the second Distance.z case the usage of "V" is completely pointless since it's always 0. Also the Distance.x if statements are also pointless as no matter the value you do the same thing in both cases.
Apart from all those things i don't see how this could possibly calculate an angle. You divide the "rectangular signed area" of your distance vector by the square root of the length of your distance. This won't give you an angle, neither in radians nor in degree. Since your "V" is set to 180 we have to assume you expect degree from your calculations.
Just try some values. For example x=3 and y=4. This gives x*y == 12. The magnitude of the vector is "5". So 12/sqrt(5) == 5.366... However the actual angle of this vector is 53.12 degree. Furthermore if you scale your vector by 2, the direction doesn't change. However your calculation returns a different value. So for x=6 and y=8, x*y ==48. The magnitude is 10. 48/sqrt(10) == 15.17
This just makes no sense.
.hmm. interesting, ins$$anonymous$$d of using it and try it you went critical about it. this a strange response.
its based on logic not mathematics. which is a strange thing to say because math is logical....however, the objects distance is used as a scale. then the on that scale you use the difference or Ratio. and then since its s quadrant you have to use conditions of left hand quadrant system. it gives you the angle to rotate in Euler angles. Its an Alternative to look at because look at has a strange axis problem. i posted this so people who want custom control on the look at they can use it to their benefit. the angle is in degrees, the ratio between the length to its local position, length being self divided to its percentage of its area.
.. the self Rotate is for asigning, a modified or mobile object that will rotate or flip. then for its location with rotation the class can adapt. its not used here though. you can ignore that, but you will need it for modification of the code.This one is good for static objects. or forward vectors. like i mentioned it is there for modification. plus, please Calculate it again. with vectors.XYZ coordinates. if you have more confusion i'm happy to discuss.
Answer by syclamoth · May 01, 2012 at 06:50 AM
There's an overload for LookRotation that allows you to specify the 'Up' vector. Just change that line to
Quaternion newRotation = Quaternion.LookRotation( direction.normalized, transform.right);
and you should be sorted.
Thanks for the suggestion $$anonymous$$ieren, but I've already tried that a few times and it doesn't work, since I need my rotation to happen on the up vector to turn the vehicle left/right, and if I change it to transform.right, it rotates the vehicle on the X axis and still tries to point the transform.forward axis towards the next target.
Stephane
Your answer
Follow this Question
Related Questions
Keeping track of vehicle rotation? 1 Answer
Writing a custom LookAt() function 2 Answers
How to get rigidbody local z axis rotation in Euler angles? 0 Answers
Why can't I assign a rotation to a rigidbody Object? 1 Answer
Using Quaternion.LookRotation( ) on y axis only, but keep x axis of transform the same? 2 Answers