If I initialize Quaternion_2 following way everything the works fine:
Quaternion_2 = someobject.transform.rotation
If I initialize it manually with some random numbers from 0 to 1 it starts rotation at normal speed and slows down at the end:
Quaternion Quaternion_2 = new Quaternion (0.5, 0.5, 0.5, 0.5);
âIf I do some really weird nonsensical thing, some really weird stuff happens. Why?â
It sounds like you already know the correct answer to this - whatâs your actual issue youâre trying to solve? Plugging random numbers into a quaternion is going to come up with some weird results. Thatâs expected.
When creating a quat, you may want to create it using something like:
var rot = Quaternion.Euler(x,y,z);
âŚ
A little breakdown/background
The 4 values in the quat have very specific meaning that relate to 3 complex numbers and 1 real number. When normalized these values can be used to represent an orientation in 3-space.
The mathematical reason that this works is fairly complex and relies on some pretty advanced knowledge about complex number theory. Itâs literally called âcomplex number theoryâ, for example a complex number with 2 dimensions can be written as:
a + bi
Where i*i = -1 (i = sqrt(-1))
What you can do then is actually graph this in a 2d grid with a as the x axis, and b as the y axis.
You can represent this as a vector in shape:
<a,b>
And with this you can actually represent a simple rotation:
Well with a quat what is going on is we extend the concept to 4 dimensions:
a + bi + cj + dk
(note a is the real component since it has no i,j,k multiplied by it)
Where i,j,k are all complex. But not necessarily just that ii = -1 way. Instead itâs that:
ii = jj = kk = ijk = -1
And if this is normalized this can be used to represent a hypersphere whose projection into 3-space (which is a sphere) will be rotated to some orientation based on a,b,c,d.
And this can all be represented as a vector:
<a,b,c,d>
Or in unity the vector values are reorganized and renamed to:
<x,y,z,w>
where w is the real component (think like how you could do rgba, or argb, for color⌠order doesnât actually matter as long as youâre aware which order was chosen).
If you want an in depth⌠this guy does a fantastic job, better than I ever could, especially since he has visuals to go with it:
With all that said⌠you donât need to know this
You donât need care about what the x,y,z,w values are in a quat, and you donât have to modify them ever.
You just use them for rotational arithmetic.
When you want to declare a rotation you can just use euler which is way more human readable. Itâs just that euler arithmetic will result in gotchas like gimbal lock. But as long as you donât do euler arithmetic, youâre safe.
(note the order of operations matters in quats⌠this is different if we put the transformâs rotation after the Quat.Euler. It changes what rotation is relative to the other. So basically if itâs 90 around the global y-axis, or 90 around the transformâs up axis)
To perform a rotation around the y-axis of 90 degrees.
Where as if you did:
transform.eulerAngles += new Vector3(0f, 90f, 0f);
Well this MIGHT work⌠depends on the orientation of âtransformâ. If the orientation was <0,0,0> itâd work just fine. But if it was rotated around say its x-axis you might get some odd behaviour where it doesnât seem to rotate at all.
This += vec is what I mean by âeuler arithmeticâ. You perform an arithmetic operation using the euler representation.
Donât do that. Use the quat representation for the arithmetic.
Use the euler for reading/writing.
And you can just use the Euler function, and eulerAngles property, to convert.
Well, thatâs not strictly true. First of all itâs a Quaternion (Quat == Four), so watch your spelling. Second plugging in random numbers into a quaternion is a valid quaternion, but not a valid unit quaternion. Quaternions, just like complex numbers, in essence represent a rotation and a scaling. Only unit quaternions do not scale and are pure rotations as they have a magnitude of 1.0.
Your example quaternion is actually a valid unit quaternion as itâs a 120° rotation around the diagonal axis (1,1,1). The âwâ value is the cosine of half the angle that the quaternion represents. Since you set w to 0.5 we get 60° when using asin. Since thatâs just half the angle the total angle is 120°. The other 3 components represent the axis we rotate around. Itâs a normalized direction vector that is multiplied by the sine of 60° (again, half the angle). The overall magnitude of that quaternion is exactly 1. The corresponding euler angles for this quaternion would be (0, 90, 90). Just think about a cube that is rotated around itâs diagonal axis. 120° is exactly 1/3 of 360° Since rotating a cube around a corner has a 3 step symetry, the cube will still look like a cube because in terms of euler angles it got rotated twice by 90° around two major axes.
Quaternions could actually be used instead of vectors to represent directions and positions and those could be added just like vectors. Actually when you rotate a point by a quaternion, thatâs actually what you have to do anyways. Though for most applications, vectors are easier to use when it comes to positions or directions. In Unity the Quaternion class exclusively represent unit quaternions for rotations / orientations.
Note even a quaternion represents a single axis and an angle around that axis, itâs not always that easy to see which axis this actually is. The amazing thing to realise is that you can get from any orientation to any other orientation by rotating around a single axis by a certain amount of degrees. This always works which is the reason why quaternions are so much better at interpolating and animating rotations. Though for animations quaternions also have some limitations as they can not represent rotations greater than 360°. So you can not have a rotation that spins an object 3 times around the same axis since subtracting or adding 360° from / to an angle does not change the resulting orientation.
Anyways, Iâm with lordofduct that itâs not really necessary to understand quaternions in and out. Itâs enough to know how to use them. It helps when you keep in mind what they represent on an abstract level (a single rotation axis and a certain amount to rotate around that axis)
Guys thank you a lot! That really helped me to understand quaternions at some point. Few days ago I even hired a math professor to get some math lessons⌠Now I am not sure that I need to go quaternions so deep, so I asked him to go some linear algebra instead May be I will push it and go for quaternions at some point.
Still I donât get why this rotation is not carried out like a single move
Quaternion Quaternion_2 = new Quaternion (0.5, 0.5, 0.5, 0.5);
it make some rotation at constant fast speed and then slows down and makes small and very slow angular turning
this never happen if I set Quaternion_2 with Quaternion.Euler(x,y,z);
Well, specifically the quaternion youâve shown new Quaternion (0.5, 0.5, 0.5, 0.5); does work for me just fine when I use RotateTowards. As I explained above this specific example is a valid unit quaternion and is equal to Quaternion.Euler(0, 90, 90);. This literalls returns a quaternion that is (0.5, 0.5, 0.5, 0.5). So Iâm not sure what you mean when you say it doesnât work. As we said, using just random numbers would not work, as the resulting quaternion would not be a normalized unit quaternion.
If youâre looking for a random rotation, Unity already has methods for this like Random.rotation. As you can read in the documentation it actually constructs a random quaternion by randomizing all elements to values between -1 and 1 and then it normalizes the result. Thereâs also Random.rotationUniform which as the name suggests has a better random distribution.
As I said above, I tried your example quaternion as a RotateTowards target and it rotates perfectly linearly towards that orientation, no matter the start orientation. Are you sure that you donât have other code that is messing around with the orientation of the object? Also youâre using transform.rotation. If the object is a child of another object, when the parent rotates it would also affect the children. You only showed us that single line of code.
Btw: It makes no sense to use Time.fixedDeltaTime anywhere. Time.deltaTime would automatically return the correct delta time value depending on where itâs used. Inside FixedUpdate (the only place where fixedDeltaTime has any meaning) Time.deltaTime will return the value of fixedDeltaTime.
I tried this code in new empty project, it does very slow angular turning in end of trajectory.:
void FixedUpdate()
{
transform.rotation = Quaternion.RotateTowards(transform.rotation, new Quaternion(0.5f, 0.5f, 0, 0), 1);
}
While Quaternion(0.5f, 0.5f, 0.5f, 0.5f) works just fine as you said.
Well, it seems you have read all our answers and replies but you havenât understood a single bit about quaternions ^^. In order to have a valid pure rotation quaternion it needs to be normalized. This new Quaternion(0.5f, 0.5f, 0, 0) is not normalized. Use the pythagorean theorem and you find out that sqrt(0.5² + 0.5² + 0² + 0²) is equal to sqrt(0.25 + 0.25 + 0 + 0) which is just sqrt(0.5). So your quaternion does not have a length of 1.0 as it should, but just a length of about 0.707. As I said above the example quaternion you have posted originally, specificallynew Quaternion(0.5, 0.5, 0.5, 0.5) is normalized and therefore a pure rotation.
I also linked the documentation to the Random.rotation which even explains that it creates the random orientation by randomizing all 4 elements and then normalizing the result. However you didnât normalize your quaternion. When you use Quaternion.Normalize(new Quaternion(0.5f, 0.5f, 0, 0)) you would actually get a quaternion that looks something like 0.7071068, 0.7071068, 0, 0. This is a 180° rotation around the diagonal of the x-y-plane and is a valid pure rotation quaternion.
The math for rotation only works out the way we want when the quaternions we use are normalized, always.