- Home /
Return Camera Rotation Z axis to 0
I'm trying to understand how to properly adjust the axis of rotation and return the z axis only to zero, leaving the x,y alone.
What I want to happen is for the camera to swing on the Z axis when trip = true and return to 0(it's original position) when false.
Here's what I have but it adjusts all the axis of rotation not just Z:
function Update (){
var currentZ = Camera.main.transform.rotation.z;
if (trip == true){
Camera.main.transform.Rotate (0,0,Mathf.Sin(Time.time)*0.3);
}
if (tTripOut < 1.0 && trip == false) {
tTripOut += Time.deltaTime/tduration;
currentZ = Mathf.Lerp(currentZ, 0f, tTripOut);
Camera.main.transform.rotation.z = currentZ;
}
PlayerMoveController
#pragma strict
// Objects to drag in
public var motor : MovementMotor;
public var character : Transform;
public var cursorPrefab : GameObject;
public var joystickPrefab : GameObject;
// Settings
public var cameraSmoothing : float = 0.01;
public var cameraPreview : float = 2.0f;
// Cursor settings
public var cursorPlaneHeight : float = 0;
public var cursorFacingCamera : float = 0;
public var cursorSmallerWithDistance : float = 0;
public var cursorSmallerWhenClose : float = 1;
// Private memeber data
private var mainCamera : Camera;
private var cursorObject : Transform;
private var joystickLeft : Joystick;
private var joystickRight : Joystick;
private var mainCameraTransform : Transform;
private var cameraVelocity : Vector3 = Vector3.zero;
private var cameraOffset : Vector3 = Vector3.zero;
private var initOffsetToPlayer : Vector3;
// Prepare a cursor point varibale. This is the mouse position on PC and controlled by the thumbstick on mobiles.
private var cursorScreenPosition : Vector3;
private var playerMovementPlane : Plane;
private var joystickRightGO : GameObject;
private var screenMovementSpace : Quaternion;
private var screenMovementForward : Vector3;
private var screenMovementRight : Vector3;
function Awake () {
motor.movementDirection = Vector2.zero;
motor.facingDirection = Vector2.zero;
// Set main camera
mainCamera = Camera.main;
mainCameraTransform = mainCamera.transform;
// Ensure we have character set
// Default to using the transform this component is on
if (!character)
character = transform;
initOffsetToPlayer = mainCameraTransform.position - character.position;
#if UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 || UNITY_BLACKBERRY
if (joystickPrefab) {
// Create left joystick
var joystickLeftGO : GameObject = Instantiate (joystickPrefab) as GameObject;
joystickLeftGO.name = "Joystick Left";
joystickLeft = joystickLeftGO.GetComponent.<Joystick> ();
// Create right joystick
joystickRightGO = Instantiate (joystickPrefab) as GameObject;
joystickRightGO.name = "Joystick Right";
joystickRight = joystickRightGO.GetComponent.<Joystick> ();
}
#elif !UNITY_FLASH
if (cursorPrefab) {
cursorObject = (Instantiate (cursorPrefab) as GameObject).transform;
}
#endif
// Save camera offset so we can use it in the first frame
cameraOffset = mainCameraTransform.position - character.position;
// Set the initial cursor position to the center of the screen
cursorScreenPosition = Vector3 (0.5 * Screen.width, 0.5 * Screen.height, 0);
// caching movement plane
playerMovementPlane = new Plane (character.up, character.position + character.up * cursorPlaneHeight);
}
function Start () {
#if UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 || UNITY_BLACKBERRY
// Move to right side of screen
var guiTex : GUITexture = joystickRightGO.GetComponent.<GUITexture> ();
guiTex.pixelInset.x = Screen.width - guiTex.pixelInset.x - guiTex.pixelInset.width;
#endif
// it's fine to calculate this on Start () as the camera is static in rotation
screenMovementSpace = Quaternion.Euler (0, mainCameraTransform.eulerAngles.y, 0);
screenMovementForward = screenMovementSpace * Vector3.forward;
screenMovementRight = screenMovementSpace * Vector3.right;
}
function OnDisable () {
if (joystickLeft)
joystickLeft.enabled = false;
if (joystickRight)
joystickRight.enabled = false;
}
function OnEnable () {
if (joystickLeft)
joystickLeft.enabled = true;
if (joystickRight)
joystickRight.enabled = true;
}
function Update () {
// HANDLE CHARACTER MOVEMENT DIRECTION
#if UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 || UNITY_BLACKBERRY
motor.movementDirection = joystickLeft.position.x * screenMovementRight + joystickLeft.position.y * screenMovementForward;
#else
motor.movementDirection = Input.GetAxis ("Horizontal") * screenMovementRight + Input.GetAxis ("Vertical") * screenMovementForward;
#endif
// Make sure the direction vector doesn't exceed a length of 1
// so the character can't move faster diagonally than horizontally or vertically
if (motor.movementDirection.sqrMagnitude > 1)
motor.movementDirection.Normalize();
// HANDLE CHARACTER FACING DIRECTION AND SCREEN FOCUS POINT
// First update the camera position to take into account how much the character moved since last frame
//mainCameraTransform.position = Vector3.Lerp (mainCameraTransform.position, character.position + cameraOffset, Time.deltaTime * 45.0f * deathSmoothoutMultiplier);
// Set up the movement plane of the character, so screenpositions
// can be converted into world positions on this plane
//playerMovementPlane = new Plane (Vector3.up, character.position + character.up * cursorPlaneHeight);
// optimization (instead of newing Plane):
playerMovementPlane.normal = character.up;
playerMovementPlane.distance = -character.position.y + cursorPlaneHeight;
// used to adjust the camera based on cursor or joystick position
var cameraAdjustmentVector : Vector3 = Vector3.zero;
#if UNITY_IPHONE || UNITY_ANDROID || UNITY_WP8 || UNITY_BLACKBERRY
// On mobiles, use the thumb stick and convert it into screen movement space
motor.facingDirection = joystickRight.position.x * screenMovementRight + joystickRight.position.y * screenMovementForward;
cameraAdjustmentVector = motor.facingDirection;
#else
#if !UNITY_EDITOR && (UNITY_XBOX360 || UNITY_PS3)
// On consoles use the analog sticks
var axisX : float = Input.GetAxis("LookHorizontal");
var axisY : float = Input.GetAxis("LookVertical");
motor.facingDirection = axisX * screenMovementRight + axisY * screenMovementForward;
cameraAdjustmentVector = motor.facingDirection;
#else
// On PC, the cursor point is the mouse position
var cursorScreenPosition : Vector3 = Input.mousePosition;
// Find out where the mouse ray intersects with the movement plane of the player
var cursorWorldPosition : Vector3 = ScreenPointToWorldPointOnPlane (cursorScreenPosition, playerMovementPlane, mainCamera);
var halfWidth : float = Screen.width / 2.0f;
var halfHeight : float = Screen.height / 2.0f;
var maxHalf : float = Mathf.Max (halfWidth, halfHeight);
// Acquire the relative screen position
var posRel : Vector3 = cursorScreenPosition - Vector3 (halfWidth, halfHeight, cursorScreenPosition.z);
posRel.x /= maxHalf;
posRel.y /= maxHalf;
cameraAdjustmentVector = posRel.x * screenMovementRight + posRel.y * screenMovementForward;
cameraAdjustmentVector.y = 0.0;
// The facing direction is the direction from the character to the cursor world position
motor.facingDirection = (cursorWorldPosition - character.position);
motor.facingDirection.y = 0;
// Draw the cursor nicely
HandleCursorAlignment (cursorWorldPosition);
#endif
#endif
// HANDLE CAMERA POSITION
// Set the target position of the camera to point at the focus point
var cameraTargetPosition : Vector3 = character.position + initOffsetToPlayer + cameraAdjustmentVector * cameraPreview;
// Apply some smoothing to the camera movement
mainCameraTransform.position = Vector3.SmoothDamp (mainCameraTransform.position, cameraTargetPosition, cameraVelocity, cameraSmoothing);
// Save camera offset so we can use it in the next frame
cameraOffset = mainCameraTransform.position - character.position;
}
public static function PlaneRayIntersection (plane : Plane, ray : Ray) : Vector3 {
var dist : float;
plane.Raycast (ray, dist);
return ray.GetPoint (dist);
}
public static function ScreenPointToWorldPointOnPlane (screenPoint : Vector3, plane : Plane, camera : Camera) : Vector3 {
// Set up a ray corresponding to the screen position
var ray : Ray = camera.ScreenPointToRay (screenPoint);
// Find out where the ray intersects with the plane
return PlaneRayIntersection (plane, ray);
}
function HandleCursorAlignment (cursorWorldPosition : Vector3) {
if (!cursorObject)
return;
// HANDLE CURSOR POSITION
// Set the position of the cursor object
cursorObject.position = cursorWorldPosition;
#if !UNITY_FLASH
// Hide mouse cursor when within screen area, since we're showing game cursor instead
Screen.showCursor = (Input.mousePosition.x < 0 || Input.mousePosition.x > Screen.width || Input.mousePosition.y < 0 || Input.mousePosition.y > Screen.height);
#endif
// HANDLE CURSOR ROTATION
var cursorWorldRotation : Quaternion = cursorObject.rotation;
if (motor.facingDirection != Vector3.zero)
cursorWorldRotation = Quaternion.LookRotation (motor.facingDirection);
// Calculate cursor billboard rotation
var cursorScreenspaceDirection : Vector3 = Input.mousePosition - mainCamera.WorldToScreenPoint (transform.position + character.up * cursorPlaneHeight);
cursorScreenspaceDirection.z = 0;
var cursorBillboardRotation : Quaternion = mainCameraTransform.rotation * Quaternion.LookRotation (cursorScreenspaceDirection, -Vector3.forward);
// Set cursor rotation
cursorObject.rotation = Quaternion.Slerp (cursorWorldRotation, cursorBillboardRotation, cursorFacingCamera);
// HANDLE CURSOR SCALING
// The cursor is placed in the world so it gets smaller with perspective.
// Scale it by the inverse of the distance to the camera plane to compensate for that.
var compensatedScale : float = 0.1 * Vector3.Dot (cursorWorldPosition - mainCameraTransform.position, mainCameraTransform.forward);
// Make the cursor smaller when close to character
var cursorScaleMultiplier : float = Mathf.Lerp (0.7, 1.0, Mathf.InverseLerp (0.5, 4.0, motor.facingDirection.magnitude));
// Set the scale of the cursor
cursorObject.localScale = Vector3.one * Mathf.Lerp (compensatedScale, 1, cursorSmallerWithDistance) * cursorScaleMultiplier;
// DEBUG - REMOVE LATER
if (Input.GetKey(KeyCode.O)) cursorFacingCamera += Time.deltaTime * 0.5;
if (Input.GetKey(KeyCode.P)) cursorFacingCamera -= Time.deltaTime * 0.5;
cursorFacingCamera = Mathf.Clamp01(cursorFacingCamera);
if (Input.GetKey(KeyCode.K)) cursorSmallerWithDistance += Time.deltaTime * 0.5;
if (Input.GetKey(KeyCode.L)) cursorSmallerWithDistance -= Time.deltaTime * 0.5;
cursorSmallerWithDistance = Mathf.Clamp01(cursorSmallerWithDistance);
}
Answer by drak8888 · Nov 23, 2013 at 12:41 AM
You should use transform.rotation.eulerAngles.z instead.
transform.rotation alone uses quaternion which is a whole lot more complicated and I doubt you were trying to fiddle with that.
Actually they should use Quatnernions if they want to smoothly interpolate between two angles. There are plenty of utility functions to help do this, although admittedly they can be a little tricky to apply the first time you encounter them. I'd maybe look at Slerp or RotateTowards.
Answer by aldonaletto · Nov 23, 2013 at 12:59 AM
This doesn't work because transform.rotation is a Quaternion, whose XYZW components have nothing to do with the angles you see in the Inspector - they are actually transform.eulerAngles. Even if you replaced transform.rotation with transform.eulerAngles, however, this would not work: currentZ is refreshed every Update, thus there's no initial rotation to return to.
What do you wanna do? Swing the camera about its local Z axis while trip is true, then return smoothly to the initial rotation when it becomes false? This depends highly on the camera hierarchy, but basically the simplest way is to child the camera to an empty object and reset its rotation - this would make things way easier:
public var maxAngle: float = 5; // max angle in degrees to each side
public var swingSpeed: float = 2; // controls swing speed
public var returnSpeed: float = 6; // controls return to zero speed
private var curEuler: Vector3 = Vector3.zero;
private var t: float = 0; // swing time
function Update(){
if (trip){
t += Time.deltaTime; // increment swing time
// swing angle between +/- maxAngle
curEuler.z = Mathf.Sin(swingSpeed * t) * maxAngle;
} else {
t = 0; // clear swing time
// return gradually to zero
curEuler.z = Mathf.Lerp(curEuler.z, 0, returnSpeed * Time.deltaTime);
}
Camera.main.transform.localEulerAngles = curEuler;
}
NOTE: if the camera originally was childed to some other object (the First Person Controller prefab, for instance), the empty should be "sandwiched" between them, and any movement/rotation script the camera initially had (like MouseLook in the FPC prefab) should be moved to the empty.
This might be too difficult for me to parse the correct script to the empty. I've attached the Player$$anonymous$$oveController script above. What should I move to the empty parent?
BTW, yes, you guessed what my intent was with the script; if triggered the camera would swing/rotate until the player exited the trigger area and return to zero at a defined rate.
Your answer
Follow this Question
Related Questions
3D effect with new UI system 1 Answer
Rotate camera only in 2 directions based on player touch 1 Answer
Mouse Orbit snapping issues 0 Answers
Turning character with transform.Rotate 0 Answers