# Using Transform.Rotate()

Discussion in 'Scripting' started by tsphillips, Jan 17, 2006.

1. ### tsphillips

Joined:
Jan 9, 2006
Posts:
359
Transform.Rotate() seems to be doing "extra" rotations, and I'm not sure why.

Consider the following code, which is attached to a flattened cube (like a plane, though I will call it a board). It allows the user to tilt the board using the arrow keys. The tilt is constrained, though, so flipping the board is impossible.

Code (csharp):
1.
2. var tilt_rate = 100.0;
3.
4. function FixedUpdate () {
5.
6.     if (Input.GetKey("left")
7.             (transform.localEulerAngles.x > 350 || transform.localEulerAngles.x < 15) ) {
8.         transform.Rotate(Vector3.left * Time.deltaTime * tilt_rate);
9.     } // if right
10.
11.     if (Input.GetKey("right")
12.             (transform.localEulerAngles.x > 345 || transform.localEulerAngles.x < 10) ) {
13.         transform.Rotate(Vector3.right * Time.deltaTime * tilt_rate);
14.     } // if right
15.
16.     if (Input.GetKey("down")
17.             (transform.localEulerAngles.z > 350 || transform.localEulerAngles.z < 15) ) {
18.         transform.Rotate(Vector3.back * Time.deltaTime * tilt_rate);
19.     } // if right
20.
21.     if (Input.GetKey("up")
22.             (transform.localEulerAngles.z > 345 || transform.localEulerAngles.z < 10) ) {
23.         transform.Rotate(Vector3.forward * Time.deltaTime * tilt_rate);
24.     } // if right
25.
26.     if (Input.GetKey("space")) {
27.         transform.localRotation = Quaternion.identity;
28.     } // if space
29.
30. } // FixedUpdate()
31.
If the direction keys are continuously pressed in rotational order (up, right, down, left, up, right, etc.) then the board will rotate through the Y axis. Visually this looks like the board rotating around on a lazy Susan, or having the camera rotate around the board.

Does anyone know why this Y axis drift is occuring, and what I can do to prevent it?

Tom

2. ### NicholasFrancis

Joined:
Apr 8, 2005
Posts:
1,587
Be very careful about using euler angles. Changing one can easily change the other.

I recommend using a transform's forward vector to determine stuff about where it's facing rather than euler angles.

### Unity Technologies

Joined:
Mar 16, 2005
Posts:
5,203
Can't see exactly where your rotations go wrong, but some suggestions to make the whole script a lot simpler

1. store x and y rotation as a float
Code (csharp):
1.
2. var x = 0.0;
3. var y = 0.0;
4.
2. Every frame, add x and y by Input.GetAxis("Horizontal") / Input.GetAxis("Vertical").
Code (csharp):
1.
2. x += Input.GetAxis("Horizontal") * Time.deltaTime * speed;
3.
3. Then clamp x and y using Mathf.Clamp
4. Apply the rotation using
Code (csharp):
1.
2. transform.rotation = Quaternion.identity;
3. transform.Rotate(x, 0, y);
4.

4. ### tsphillips

Joined:
Jan 9, 2006
Posts:
359
I'm careful not to modify the Euler angles (here) -- just wanted to know the rotation relative to the parent. I did see the forward vector code in the physics demo (making the car untopple itself), but didn't quite follow how that was working. (I didn't know how to interpret "transform.rotation * Vector3.fwd". A 1x4 vector times a 1x3 vector? But then, my matrix algebra is almost 20 years old...)

To solve the Y axis rotation problem I ended up fixing the Y rotation at the end of the script.
Code (csharp):
1.
2. transform.localEulerAngles.y = 0;
3.
(Okay, it's fixing an Euler angle, but it looks safe. :wink: )

The GetAxis() example certainly looks more straightfoward. Are scripts atomic? That is, is there any chance a script could be interrupted between these two lines?

Code (csharp):
1.
2. transform.rotation = Quaternion.identity;
3. transform.Rotate(x, 0, y);
4.
Tom

### Unity Technologies

Joined:
Mar 16, 2005
Posts:
5,203
Unity will never interrupt a script function execution on it's own.

But you can tell unity to pause execution using coroutines. Coroutines are a great concept. They can simplify code a lot when you have to deal with behaviours/events over time. Which games happen to do a lot.

http://www.otee.dk/Documentation/ScriptReference/index.html#The Yield Statement

6. ### NCarter

Joined:
Sep 3, 2005
Posts:
686
That's a quaternion 'multiplied' by a vector, which is the usual notation for "rotate this vector by this quaternion". So, for example:

Code (csharp):
1. localForwardVector = transform.rotation * Vector3.forward;
Quaternions are essentially 4D vectors, but you may as well ignore that detail, and just concentrate on thinking of them as rotations which can be used to rotate vectors and objects.

7. ### NicholasFrancis

Joined:
Apr 8, 2005
Posts:
1,587
I've just been informed by Joe that our Lerps all clamp between 0 and 1. Hence you don't need to worry about the last step.

Joined:
Jan 9, 2006
Posts:
359