Quaternion rotates, then comes back, then rotates...

Hi,

I have got a weird effect and I can’t manage to resolve it, when I rotate the character in Euler X or Euler Y with the code below, it stops after around 80° (no matter at which degree it is), then it comes back 20° lower, and then it goes back for 80° again, and does this all the time, when I push the “Y” or “X” key.

Would you know why?

Here is the code I am using : (so I think it goes like this: it takes 10 steps to go from the previous rotation to the next one, with a value of +5 in X or Y)

#pragma strict

public var thisTransform : Transform;
public var thisTransformTargetRotation : Quaternion;

public var addAngle : float = 5;
private var floatX : float;
private var floatY : float;
private var floatZ : float;

function Start () {
	thisTransform = GetComponent(Transform);
	
	floatX = thisTransform.eulerAngles.x;
	floatY = thisTransform.eulerAngles.y;
	floatZ = thisTransform.eulerAngles.z;
	
	rotate();
}

function rotate(){
	
	thisTransformTargetRotation = Quaternion.Euler(Vector3(floatX, floatY, floatZ));
	thisTransform.rotation = Quaternion.RotateTowards(thisTransform.rotation, thisTransformTargetRotation, Time.deltaTime*100);
}

function Update () {
	
	if ( Input.GetKey("y") ) {
		floatY += addAngle;
		rotate();
	}
	if ( Input.GetKey("x") ) {
		floatX += addAngle;
		rotate();
	}
	
}

Thanks

Try this. I didn’t evaluate why your script was causing the odd behavior, but it probably had something to do with the use of RotateTowards. I just assigned the Quaternion.Euler rotation directly to the GameObject’s rotation and it appears to work fine. Also, every script component has direct access to the GameObject’s transform via the “transform” property. You don’t have to access it with a GetComponent() call.

#pragma strict
 
public var addAngle : float = 5;
private var floatX : float;
private var floatY : float;
private var floatZ : float;
 
function Start () {

    floatX = transform.eulerAngles.x;
    floatY = transform.eulerAngles.y;
    floatZ = transform.eulerAngles.z;
 
    rotate();
}
 
function rotate(){
 
    transform.rotation = Quaternion.Euler(floatX, floatY, floatZ);
}
 
function Update () {
 
    if ( Input.GetKey("y") ) {
       floatY += addAngle;
       rotate();
    }
    if ( Input.GetKey("x") ) {
       floatX += addAngle;
       rotate();
    }
 
}

And if you want the rotation to be always smooth and consistent, you can multiply it by Time.deltatime when adding it - that way you’ll get consistent rotation on any system. Just think of the addAngle as angles per second.

    if ( Input.GetKey("y") ) {
       floatY += addAngle*Time.deltaTime;
       rotate();
    }
    if ( Input.GetKey("x") ) {
       floatX += addAngle*Time.deltaTime;
       rotate();
    }

There are several things going on with your code. First, RotateTowards() is lazy. It will always take the shortest angle between two rotations. Next, you are using Input.GetKey() which returns true for every frame the key is pressed down, so you are getting multiple additions of ‘addAngle’ for every key press. And finally you are only calling your rotate method while the key is down. Combining these three things, what is happening is that your
‘thisTransformTargetRotation’ is getting way ahead of your transform’s rotation. When that happens, RotateTowards(), being the lazy function that it is, starts heading backwards to the position specified, but then your rotation again passes the point of the current rotation and it heads forward.

I don’t know what your intended behavior is, but if you just want to rotate smoothly based while a key is held down, you can do something simpler:

var speed = 35.0; // Degrees per second

function Update () {
 
    if ( Input.GetKey("y") ) {
       transform.Rotate(Vector3(0,speed*Time.deltaTime,0));
    }
    if ( Input.GetKey("x") ) {
       transform.Rotate(Vector3(speed*Time.deltaTime,0,0));
    }
}

As a side note, take a look at the reference page for GameObject. It has instance variables for some of the commonly used components, so you don’t have to do a GetComponent to get the transform.