Rotation script working only in one instance

Hi all,

Okay, here’s one that’s got me stumped. It might be the simplest problem, but I need new eyes looking over it; I can’t figure out what’s wrong.

So the situation is this: I’ve started to make an in-game menu using objects such as cubes with OnMouseDown() functions as opposed to using the Unity GUI. Because of that I’ve made it so each section of the menu (Main menu, options menu, etc) are in a different space in the scene, and when one transitions to another, the camera rotates to look at the new menu. For example, I click the ‘Options’ button in the Main Menu, and the camera rotates 90 degrees down to see the Options Menu.

Here’s the relevant code attached to one of my button objects:

private var mainCamera : GameObject;

function Start()
{
	mainCamera = GameObject.Find("Main Camera");
}

function OnMouseDown()
{
	mainCamera.SendMessage("LookUp");
}

The only difference in the code between the two buttons is one sends a “LookUp” message to the camera, and the other sends a “LookDown” message. And the code attached to my Main Camera object:

var rotateSpeed : float;
private var endAngle : int;
private var lookUp : boolean;
private var lookDown : boolean;

function LookUp()
{
	endAngle = transform.eulerAngles.x - 90;
	if(endAngle == -90)
	{
		endAngle = 270;
	}
	lookUp = true;
}

function LookDown()
{
	endAngle = transform.eulerAngles.x + 90;
	if(endAngle == 360)
	{
		endAngle = 0;
	}
	lookDown = true;
}


function Update()
{
	if(lookUp == true)
	{
		transform.eulerAngles.x -= rotateSpeed;
		if(transform.eulerAngles.x > endAngle - 1 && transform.eulerAngles.x < endAngle + 1)
		{
			lookUp = false;
			transform.eulerAngles.x = endAngle;
		}
	}
	if(lookDown == true)
	{
		transform.eulerAngles.x += rotateSpeed;
		if(transform.eulerAngles.x > endAngle - 1 && transform.eulerAngles.x < endAngle + 1)
		{
			lookDown = false;
			transform.eulerAngles.x = endAngle;
		}
	}
}

(Lerping and such never seems to work for me, so this is a crude workaround)

This all works perfectly fine from the first menu, going both up and down, however when I try to go back from either of the other menus (using the same scripts attached to different objects) it never works. The camera jitters once then stops completely.

I’ve been trying to figure this one out for hours now, and I hate leaving a problem unsolved before bed, but its got to be done, I’m at my wits end!

Thanks for your help!

You can’t rely on eulerAngles to make rotations this way: eulerAngles are actually transform.rotation converted to 3-axes format, and since this is a redundant representation, different x, y, z combinations may be returned at some points of the rotation.

The best way to do that is to save the initial eulerAngles in a Vector3 variable at Start, then “rotate” the desired angle by math, assigning it to eulerAngles each Update. You could also use Mathf.MoveTowards to change the angle x smoothly, and multiply rotateSpeed by Time.deltaTime to make it framerate independent. Using these tricks, things get much simpler:

var rotateSpeed : float; // degrees per second
private var endAngle : int;
private var euler : Vector3;

function Start()
{
    euler = transform.eulerAngles; // get the initial angles
    endAngle = euler.x; // initialize endAngle to the current x
}

function LookUp()
{
    endAngle -= 90; 
}

function LookDown()
{
    endAngle += 90;
}

function Update()
{
   euler.x = Mathf.MoveTowards(euler.x, endAngle, rotateSpeed * Time.deltaTime);
   transform.eulerAngles = euler; // update the actual eulerAngles
}

This code rotates endAngle 90 degrees up or down each time you press the buttons, and the euler variable follows it with the desired speed. MoveTowards is cool because it moves from the current euler.x value to endAngle at the desired speed, and stops moving exactly at the destination value.