Search Unity

I can't get the logic of Quaternion.LookRotation...

Discussion in 'Scripting' started by Sphynxinator, Mar 27, 2012.

  1. Sphynxinator

    Sphynxinator

    Joined:
    Jan 22, 2011
    Posts:
    44
    Hello all. My problem is obvious. I finally get the purpose of the "Quaternion.LookRotation"(it is actually "LookAt" function but it can also be used with Quaternion Class Functions, am I right?). It usually used like this(then use Quaternion.Slerp function with current position of myTransform if we want to turn the certain object into one rotation from another one):

    Code (csharp):
    1. Quaternion.LookRotation(target.position - myTransform.position);
    I can't get the logic of "target.position - myTransform.position". Why are we doing this? We want to Look at the certain "rotation" but we are using "position" of the object. Also its syntax is like this:

    Code (csharp):
    1. static function LookRotation (forward : Vector3, upwards : Vector3 = Vector3.up) : Quaternion
    We didn't used the "Vector3.up". We just wrote "target.position - myTransform.position" and closed the bracket. When we do this, are we using its default value(is its default value Vector3.up)? Also I want to rotate the object in Z axis but I am using the Y axis. It's confusing me.

    I tried to understand it, but I can't understand. I'm such a stupid, but please help me.

    Thanks...
     
    Last edited: Mar 27, 2012
  2. GibTreaty

    GibTreaty

    Joined:
    Aug 25, 2010
    Posts:
    792
    By doing target.position - myTransform.position, it turns it into a direction. That direction is then used as a forward axis I believe. Then the forward axis is modified by the upwards vector axis.

    The default value for upwards is Vector3.up. If you want to rotate on the Z axis then upwards should be set to Vector3.forward.

    I hope that helps.
     
    Last edited: Mar 27, 2012
  3. Diviner

    Diviner

    Joined:
    May 8, 2010
    Posts:
    677
  4. Sphynxinator

    Sphynxinator

    Joined:
    Jan 22, 2011
    Posts:
    44
    Thanks for the replies. Okay, "target.position - transform.position" simply calculates the distance between target and myTransform. For example, target.position is (10, 15, 2) and myTransform.position is (5, 4, -3). Then "target.position - myTransform.position" will give (5, 11, 5). It's trying to say, "if myTransform go +5 as x, +11 as y, +5 as z, it will reach to target.position". Then it will look to (5, 11, 5) + myTransform with help of Y rotate axis. Am I right? Still don't get it.

    By the way Diviner, is it a RPG Turn-based Combat System Tutorial? If it is, it will be helpful, I want to follow the tutorial, thanks. Also GIB3D, thanks you to again.
     
    Last edited: Mar 27, 2012
  5. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    target - transform moreso tells you the direction to the target from the transform.

    target = 10, transform = 5, so 10-5= 5. So in order to move towards the target you have a "distance and direction" of 5.

    In calculation, you would use something like this:

    Code (csharp):
    1.  
    2. var unmanagedDirection = (target.position - transform.position);
    3. var managedDirection = unmanagedDirection.normalized;
    4. var distance = unmanagedDirection.magnitude;
    5.  
    So with these 3 lines you can find the direction, its distance and what you would have to add to something to get movement

    Now, further down the lines, you can use directional angles.
    Code (csharp):
    1.  
    2. var angle = Vector3.Angle(transform.forward, managedDirection);
    3. var dot = Vector3.Dot(transform.right, manageDirection);
    4. angle = dot < 0 ? -angle : angle;
    5.  
    Now with this, you see an angular representation of the difference between forward and the direction.

    Now we can apply this as such:
    Code (csharp):
    1.  
    2. var angle = Vector3.Angle(transform.forward, managedDirection);
    3. var dot = Vector3.Dot(transform.right, manageDirection);
    4. var toRotation = Quaternion rotation = Quaternion.LookRotation(manageDirection, Vector3.up); // the rotation we need to go in;
    5. var rot = maxRotationDegreesPerSecond;
    6. if(angle < rot) rot = angle; // don't over rotate
    7. rot = dot < 0 ? -rot : rot; // reverse rot instead of angle
    8.  
    9. transform.rotation = Quaternion.Slerp(transform.rotation, toRotation , (rot / angle) * Time.deltaTime);
    10.  
    So now, this would take us from whatever rotation that we were at to an up vectored rotation based off of the target we are wanting to go towards.

    Now we can lastly check to see the direction and its proportion to the direction of the target. We get a Dot from both the forward direction and the target direction and we get a number:
    Code (csharp):
    1.  
    2. // remember This requires both be normalized.
    3. var toForwardDot = Vector3.Dot(transform.forward, managedDirection);
    4.  
    This gives us a number between -1 and 1. 1 is directly in front of us, and -1 is directly behind us. Zero is right, left up or down, and thus, not in front of us. So if you want to know how close you are to forward without figuring an angle. Dot is great.
     
    IndieForger likes this.
  6. Sphynxinator

    Sphynxinator

    Joined:
    Jan 22, 2011
    Posts:
    44
    Well thanks, I was asking for some simple info about LookRotation but you now talking about Dot Product and some advanced information. :D However, I learnt it now, it will be useful. Actually I learnt Dot Product with using some Print(); functions, and noticed that if it is directly in front of us it returns value 1, if it behind of us, it returns value of -1. :D I even understand what Dot Product does, but I still don't understand what LookRotation does. Especially Vector3.up in LookRotation's syntax. I'm going nuts. I'm trying to understand it for 2 days and I can't study my exams because of this. :D I'm looking the Unity Script Reference page, but it explains it as technical. I can't understand it.
     
  7. Diviner

    Diviner

    Joined:
    May 8, 2010
    Posts:
    677
    Yes, it's exactly that.
     
  8. Tseng

    Tseng

    Joined:
    Nov 29, 2010
    Posts:
    1,217
    The upwards parameter is optional.

    Code (csharp):
    1. static function LookRotation (forward : Vector3, upwards : Vector3 = Vector3.up) : Quaternion
    The first parameter, forward, is required. The second (upwards) is optional. If you don't pass a second parameter, it will default to Vector3.up.

    Code (csharp):
    1.  
    2.    Quaternion.LookRotation(direction);
    3.    Quaternion.LookRotation(direction, Vector3.up); // Equal to Quaternion.LookRotation(direction);
    4.    Quaternion.LookRotation(direction, Vector3.right); // the right direction will be handled as upwards.
    5.  
    Imagine you have a pistol. When you set the direction, the gunbarrel will point to the target. But the grip can be in any direction (down if you hold your pistol vertically or it can point to left or right if hold horizontally). In order to controll that. So when the pistol is in it's normal position, the gun barrel will be forward and Vector3.up will be upwards.

    When you use "LookRotation(direction, Vector3.left);, then the will point towards your target, but the grip will point to the left (because the pistol will be turned so that it's left side looks upwards).

    LookRotation turns the object to look in a certain direction. You get the direction - as explained above - by substractingt two positions.

    Also I don't think you understand Dot product. Dot product is only >=-1 <= 1 for normalized directions. A normalized direction ins one whose "magnitude" is exactly one. For non-normalize the Dot product can be higher/smaller than 1/-1.

    Check out this thread, especially the 2nd and 4th post.
    http://forum.unity3d.com/threads/128519-Detect-Collision-from-front-of-capsule-collider-question

    If you use two normalized directions, the Dot product will also equal to the Mathf.Cos(angle*Mathf.Deg2Rad), which can easily allow you to calculate cones (i.e. cones of vision for an AI)
     
  9. Sphynxinator

    Sphynxinator

    Joined:
    Jan 22, 2011
    Posts:
    44
    My parents thinks I will shot them because of this example(I asked them like "hey, what is a gunbarrel and grip?"). How did you learn these functions by the way. Wow.

    Okay, I have two questions:
    1-Why Quaternion.LookRotation function needs a second Vector3 value? Why it needs a upwards direction? If it's syntax was like this, what would be missing? I wrote Vector3.right instead of Vector3.up, and the object went nuts.

    Code (csharp):
    1. static function LookRotation (forward : Vector3) : Quaternion
    2-We are making the object look to the target's rotation, but we are doing this by using its position. Are we trying to say to the object that we making it look to the target, "hey, you will make a rotation, but your forward will look to the target's position"?
     
  10. Tseng

    Tseng

    Joined:
    Nov 29, 2010
    Posts:
    1,217
    Haha... sorry, that made me chuckle :p

    You could have used an online translator, though I thought it was obvious when using "pistol" as an example.

    Ok, I'll try it more visually then.
    $gun1.png

    Here is a rifle as example (sorry, didn't found any pistol, in borrowed this one from the Angry Bots demo).
    As you can see it points somewhere (not at the cube). What's important to know are the colored arrows you see.

    The BLUE arrow is the forward (transform.forward) vector. This is the guns forward direction.
    The RED arrow is the right (transform.right) vector. This points in the right direction.
    The GREEN arrow is the up (transform.up) vector. This points upwards.

    Ok so far?
    When you rotate the object (with LookAt/LookRotation, you want to make the BLUE arrow show to the target.

    With this code
    Code (csharp):
    1.  
    2.     Vector3 direction = target.position - transform.position;
    3.     transform.rotation = Quaternion.LookRotation(direction, Vector3.up); // this is same as Quaternion.LookRotation(direction);!!! Because if you only use one parameter, the second will automatically be set as Vector3.up
    4.  
    you get this image
    $gun2.png
    As you can see the BLUE arrow is pointing at the target. And the green Arrow (transfrom.up) is pointing upwards.

    Now test this code:
    Code (csharp):
    1.  
    2.     Vector3 direction = target.position - transform.position;
    3.     transform.rotation = Quaternion.LookRotation(direction, Vector3.right);
    4.  
    $gun3.png
    Now, do you notice the difference? The BLUE (transform.foward) is STILL pointing to the target, but the red arrow (transform.right) is pointing upwards (Vector3.up in world coordinates). So the weapon is no in a horizontal position (Or like an American would say: "Gangster style").

    That's why you need the second parameter. You will mostly need it, when trying to rotate bones or children, because the up vector is not always pointing upwards, or if you rotate around a certain axis.

    I don't really understand this question. I've read it several times and I'm not sure what you are asking. You need the positions of both objects, to calculate the direction. The direction is used by LookRotation to calculate an Quaternion (A Quaternion is hard to explain, it has 4 axis (x, y, z, w) unlike Angles who have only 3 axis (x, y, z)).

    This would be enough in 2-dimensional space. But in 3-dimensional space it's not enough to rotate an object. Two axis can be calculated (in above example x and y rotation) but the z rotation can't be determined without a hint. Look at the images below. They both show at the target, but the z-rotation is different (the rotation around the forward axis).

    $gun5.png

    So you must give the function a hint which axis acts as upwards. By default (when only use one parameter) the function will assume that Vector.up points upwards (logical). Sometimes this is not right (depending on the model and the bone)
     
    Last edited: Mar 27, 2012
    alpayoguz97 and Mikhail94 like this.
  11. Sphynxinator

    Sphynxinator

    Joined:
    Jan 22, 2011
    Posts:
    44
    Oh!!! I finally understand the first problem. :D Thank you so much. <3 Sorry for the confusing text though. :( I will try again to say the thought in my mind.

    I was trying to say this: LookRotation rotates the object's forward to the target's position. When we do "target.position - myTransform.position" operation, it gives how much target.position is far from myTransform.position. But how does Quaternion.LookRotation make a rotation to target's position?

    Simply, I'm saying how does Quaternion.LookRotation make a rotation when it finds the direction of the target? Does Quaternion.LookRotation say "myTransform will rotate until myTransform's forward axis(Z-Axis) looks towards target's position and myTransform's y-axis will be upwards"?
     
  12. Tseng

    Tseng

    Joined:
    Nov 29, 2010
    Posts:
    1,217
    I wouldn't use words such as "how far x is from y" when talking about the direction (3-dimensions: x, y, z) , because it can easily be confused with "distance" (1-dimension: distance).

    You can also have to different sized vectors pointing in the same direction.

    For example:
    Code (csharp):
    1.  
    2.     Vector3 direction = new Vector3(3, 1, 2); // It's magnitude is 3.742 (that's the distance, 1-dimensional)
    3.     Vector3 direction2 = new Vector(0.802, 0.267, 0.534);
    4.  
    Both vectors show in the same direction. The only difference is their length (magnitude). The magintude of the first direction is 3.742 (Because: sqrt(3*3 + 1*1 + 2*2) = 3.742). The magnitude of the second direction is 1 => sqrt(0.802*0.802 + 0.267*0.267 + 0.534*0.534) (if you ignore the rounding errors its pretty much 1).

    If you multiply direction2 with 3.742 you will get a direction which is pretty close to Vector3(3,1,2) same as doing direction.normalize will get pretty much direction2.

    direction2 is a normalized Vector, because it's length (magnitude) is 1.

    Well, Quaternion is some pretty complicated mathematics. You don't need to know it, it's used only internally and you won't basically never work with Quaternions directly only with Euler Angles and the Helper methods (such as Quaternion.LookRotation).

    I think most of the devs here can't explain you how Quaternions work (neither can I). You only need to know how they work, when making your own 3D Engine :p
     
  13. Sphynxinator

    Sphynxinator

    Joined:
    Jan 22, 2011
    Posts:
    44
    Oh, okay. You really helped me very much! You even talk about magnitude and normalizing, feels like Inception. :D A tutorial that is in another tutorial. I also feel uninformed about magnitude and normalizing vectors, but I learnt those things now. :D Real happy. I learnt all things that I need to learn and now I won't confuse direction and distance. Wow. You are really a good teacher. Hope this thread helps another people that can't understand Quaternion.LookRotation.

    Thanks all !!!
     
  14. Tobias J.

    Tobias J.

    Joined:
    Feb 21, 2012
    Posts:
    423
    yup. Was a great help for me as well. Thanks Tseng!
     
  15. muy31

    muy31

    Joined:
    Nov 29, 2020
    Posts:
    1
    Thank you a lot for that explanation Tseng!

    I am also currently working on an FPS script, but I am having issues with LookRotation/LookAt when the target position is sort of below me or above me. Then, the gun just points at a random angle (actually not random, but the identity).

    It makes some sense why this happens, but how do I get around this issue? I don't want to not be allowed to shoot at something flying above my head or below in a valley...
     
  16. alpayoguz97

    alpayoguz97

    Joined:
    Oct 10, 2020
    Posts:
    1
    Thank you. I'm very grafeul for this explanation
     
  17. Sixbreaker

    Sixbreaker

    Joined:
    Dec 29, 2016
    Posts:
    11
    ok np, i deleted it, may the Lord bless you