- Home /
How can i rotate a camera on its x or z axis using a Quaternion
Hello guys i would like to ask how can i make may camera rotate 60 degrees on its x axis when i press the Left Arrow key on the keyboard. I would be thankful if someone could help me out thank you very much in advance :)
Also one important thing how do i make it so that when i let go of the key the camera returns back to its normal position here is a script i did for gun movement but it did not work out when i tried the same for the camera rotation :)
public var MoveAmount : float = 1;
public var MoveSpeed : float = 2;
public var GUN: GameObject;
public var CAM: GameObject;
public var MoveOnX : float;
public var MoveOnY: float;
public var DefaultPos : Vector3;
public var NewGunPos : Vector3;
public var ONOff : boolean = false;
function Awake(){
DefaultPos = transform.localPosition;
ONOff = true;
}
function LateUpdate () {
if(ONOff == true){
MoveOnX = Input.GetAxis( "Mouse X") * Time.deltaTime * MoveAmount;
MoveOnY = Input.GetAxis( "Mouse Y") * Time.deltaTime * MoveAmount;
NewGunPos = new Vector3 ( DefaultPos.x+ MoveOnX, DefaultPos.y + MoveOnY, DefaultPos.z);
GUN.transform.localPosition = Vector3.Lerp(GUN.transform.localPosition , NewGunPos, MoveSpeed * Time.deltaTime);
}
else{
ONOff = false;
GUN.transform.localPosition = Vector3.Lerp(GUN.transform.localPosition, DefaultPos , MoveSpeed *Time.deltaTime);
}
}
Answer by aldonaletto · Oct 22, 2011 at 11:15 AM
That's a good job for a coroutine. Call the coroutine RotateCam when the key is pressed, and it will do the full cycle: rotate 60 degrees around X in duration seconds, wait until key released, then return to the initial position in the same time.
var duration: float = 1.2; // duration in seconds private var orig: Quaternion; private var dest: Quaternion; private var rotateCamFlag = false;
function RotateCam(){ if (rotateCamFlag) return; // aborts if already rotating rotateCamFlag = true; // flag indicates it's rotating var start = transform.rotation; // save the start rotation... var dest = Quaternion.Euler(60, 0, 0) * start; // and calculate the destination var t: float = 0; while (t = 0){ t -= Time.deltaTime/duration; // t go back to 0 a little step transform.rotation = Quaternion.Slerp(start, dest, t); // rotate this little yield; // free Unity until next frame } rotateCamFlag = false; // rotation ended } To do the magic, just call RotateCam when left arrow pressed:
if (Input.GetKeyDown("left")) RotateCam();
NOTE: This function always rotate 60 degrees, wait key up and rotates back, even if you release the key too soon.
EDITED: I tested the script above and it worked fine, but you can have the same effect without coroutines with the script below (values adapted to match the video that you linked):
private var duration: float = 0.6; // time in seconds private var orig: Quaternion; private var dest: Quaternion; private var t: float = 0;
function Update(){ // t > 0 when cycle running; avoid new cycle when t > 0 if (Input.GetKeyDown("left") && t
EDITED2: Well, this is a 3rd version - this time using Mouse X and returning to 0 rotation when the mouse stops. It seems that that's what your script does, but in this version the rotation can be changed from left to turn right and vice versa if the mouse is moved.
var duration: float = 0.2; // time in seconds var angle: float = 12; // angle to turn left or right var limit: float = 0.3; // set the sensitivity var speed : float = 100; // isn't used in this code
private var orig: Quaternion; private var dest: Quaternion; private var dir: float;
function Start(){ orig = transform.localRotation; }
function Update(){ // filter the mouse input with Lerp dir = Mathf.Lerp(dir, Input.GetAxis("Mouse X"), 5*Time.deltaTime); dest = orig; // define the dest rotation according to the dir variable if (dir > limit) dest = Quaternion.Euler(0, 0, -angle); if (dir < -limit) dest = Quaternion.Euler(0, 0, angle); transform.localRotation = Quaternion.RotateTowards(transform.localRotation, dest, angle*Time.deltaTime/duration); }
it does not work i attached the script to the players camera and when i call it from another script there is nothing going on ?
It should work. It should be part of the camera script, or a new script attached to the camera. $$anonymous$$aybe you must change transform.rotation to transform.localRotation. Anyway, I'll test this script and return asap.
The script worked fine in my tests, but I edited my answer and added an alternative that doesn't use coroutines. You can attach this script to your camera, and it will work in a way similar to the video linked. NOTE: If you have another camera control script it can fight with this one for the camera control, and one of them will not work! Disable any other camera script to test this one.
t = $$anonymous$$athf.Clamp(t, 0, 1); clamps the value of t to the range 0..1, needed for the Slerp function. In this script, the variable t is constantly incremented (when left pressed) or decremented (left released), and if not clamped it could reach too high or too low values, taking a long time to effectively turn the camera.
Yes, the dir variable holds a smoothed version of Input.GetAxis("$$anonymous$$ouse X"). Each Update, this script reads Input.GetAxis and "filter" its value in the variable dir using Lerp; the dir value stays at 0 if mouse stopped, and goes to -1 or +1 when mouse moving. Right after reading the mouse axis, the script uses the smoothed dir value to select the dest rotation: orig if dir near to 0, -angle if > limit and angle if < -limit. Anyway, RotateTowards is called each Update to move in the dest direction - if it's orig, the object returns or gets stopped at the original rotation, else it rotates to the desired angle.
Finally, the value 5 multiplied by Time.deltaTime defines the smoothing effect of the Lerp filter; if you increase it too much, the rotation may become jerky; if you reduce too much, the controls will become too slow.