Wednesday, December 3, 2014

Unity: Spherical Camera

This post discuss a simple implementation of a spherical camera in Unity Game. The complete project source can be downloaded from:

https://dl.dropboxusercontent.com/u/113201788/Unity3D/Camera.Spherical-Camera.zip

 The spherical camera has the following functionality:

1. When the user presses down the SHIFT+UP, the camera will zoom in to its focus point (i.e. a target point). The camera will zoom out while looking at the target point when user presses down the SHIFT+DOWN keys

2. When the user presses down the LEFT or RIGHT arrow key, the camera will rotate horizontally around the target point.

3. When the user presses down the UP or DOWN arrow key, the camera will rotate vertically around the target point over a range of minimum and maximum angles.

4. When the user hold down the right mouse button and drag on the terrain simultaneously, the target point will move in the same direction, and the camera move accordingly following the direction of the mouse drag motion.

To implement this, first lets create an empty game object named "target", which will act as the the focus/target point of the spherical camera (to make it more visible, a spherical game object is attached as a child to this "target" game object).

Next create a C# script and name it "SphericalCamera.cs". Update its content as shown below:

using UnityEngine;
using System.Collections;

public class SphericalCamera : MonoBehaviour {
 private float initialFOV;

 public float minZoomLimit=0.1f;
 public float maxZoomLimit=10;

 public int distance=100;
 public GameObject target = null;

 private float xRotate;
 private float yRotate;

 public float xRotateSpeed=3.0f;
 public float yRotateSpeed=1.5f;

 public float maxYRotate=90.0f;
 public float minYRotate=0.0f;

 public float xMoveSpeed=100.0f;
 public float zMoveSpeed=100.0f;

 // Use this for initialization
 void Start () {
  Vector3 angles = transform.eulerAngles;
  xRotate = angles.x;
  yRotate = angles.y;

  initialFOV = camera.fieldOfView;

  transform.position = new Vector3 (0, 0, -distance) + target.transform.position;
 }
 
 // LateUpdate is called once at the end of a frame
 void LateUpdate () {
  if(Input.GetKey(KeyCode.RightShift) || Input.GetKey(KeyCode.LeftShift))
  {
   float zoom = camera.fieldOfView - Input.GetAxis ("Vertical") * yRotateSpeed;
   if(zoom >= initialFOV / maxZoomLimit && zoom <= initialFOV / minZoomLimit)
   {
    camera.fieldOfView -= Input.GetAxis ("Vertical") * yRotateSpeed;
   }
  }
  else
  {
   xRotate += Input.GetAxis ("Horizontal") * xRotateSpeed;
   yRotate += Input.GetAxis ("Vertical") * yRotateSpeed;

   if(yRotate > 360) yRotate-=360;
   if(yRotate < -360) yRotate+=360;

   yRotate=Mathf.Clamp(yRotate, minYRotate, maxYRotate);
  }

  if(Input.GetMouseButton(1))
  {
   float target_x = Input.GetAxis ("Mouse X") * xMoveSpeed;
   float target_z = Input.GetAxis ("Mouse Y") * zMoveSpeed;
   Vector3 movement = transform.transformDirection(new Vector3(target_x, 0, target_z));
   movement.y = 0.0f;

   
   target.transform.Translate(movement);
  }

  var rotation = Quaternion.Euler (yRotate, xRotate, 0);
  var position = rotation * (new Vector3 (0, 0, -distance)) + target.transform.position;

  transform.rotation = rotation;
  transform.position = position;
 }
}


Now attach the "SphericalCamera.cs" to the "Main Camera" game object. Next with the "Main Camera" selected in the "Hierarchy" view, drag the "target" game object from the "Hierarchy" view to drop it in the "target" attribute of the "SphericalCamera.cs" in the "Inspector" view of "Main Camera". That is it.

The zooming is performed when the SHIFT key is pressed together with the UP or DOWN arrow key (i.e. KeyCode.LeftShift / KeyCode.RightShift), the change is the zooming is calculated as

Input.GetAxis("Vertical") * yRotateSpeed;

The code is fairly easy to understand once the following methods are understood:

  • Input.GetAxis("Vertical") returns the duration / extent to which the UP or DOWN arrow key is pressed.
  • Input.GetAxis("Horizontal") return the duration / extent to which the LEFT or RIGHT arrow key is pressed
  • Input.GetAxis("Mouse X") return the duration / extent to which the mouse is moved in direction x
  • Input.GetAxis("Mouse Y") return the duration / extent to which the mouse is moved in the direction y
  • Input.GetMouseButton(1) return the boolean value indicating whether the right mouse button has been pressed down.



No comments:

Post a Comment