28 Jul 2013

Unity Hacks: Cameras

In my effort to pick apart the “Unity Hacks” project as made available, along with a recording of the presentation, in the videos section, I now focus on the camera system.


Like the other new components I was preparing for the new standard assets, a key part of this setup is modularity and versatility. This is why I from the start chose to have camera handling values maintained via the transform tree – as opposed to maintaining internal values to overwrite the transform values when updated.

This way, not only can camera logic be broken down into several components which can be optional or replaced, but co-operation between the camera system, animations and any other systems which could apply relative transformation, is much easier.

As this approach would be placing a certain requirement on the transform tree structure surrounding the camera in any case, I opted to go for greatest amount of possible detail vs. smallest impact. The structure therefore requires a three layers deep transform tree.

The root of the tree is designated the horizontal hinge. It takes care of movement in all three dimensions as well as rotation on the horizontal plane. The immediate child of this transform is referred to as the vertical hinge. This transform is expected to not move and will have its position reset every frame to enforce this. In stead, the vertical hinge is only responsible for rotation on the vertical plane.

The final transform, the child of the vertical hinge, is expected to not rotate and only move on its relative z-axis. This effectively makes it the zoom component of the rig. The GameObject of this transform is the one holding the camera component.


Maintaining and abstracting this setup is the DualHingeCamera component. With reference to the different transforms of the rig, this component maintains the setup by apply three targets: targetOffset, targetHorizontalRotation and targetVerticalRotation. These are set by controller scripts and applied via constrained speed and offset variables.

Vertical rotation is clamped and damped by the verticalSpan animation curve variable. As explained in the presentation, the time value of the most extreme animation keys specify the vertical angles (relative to a vector pointing backwards from the rig root) at which vertical rotation is clamped.

The height of the curve at any point specifies the scale of the update speed – as the camera moves through that angle and further towards the end of the half of the curve it is on. As in: If the angle is above the middle of the vertical span and the camera is moving further up, speed is scaled according to the curve, but if it is moving down then no scale is applied. The inverse if of-course true as well. The effect, assuming the curve is not flat, is a smooth limit rather than a hard clamp.


The base for any of the example camera behaviours supplied with the project is the CameraBehaviour component. This supplies wrapping of access to the DualHingeCamera, as well as a bit of default handling – such as automatically updating the camera activity tracking when the camera moves. It also offers up the MoveCamera method as a common interface for input scripts to apply movement instructions.

One of the most simple examples of a camera behaviour is the OrbitCamera. This camera simply takes the movement instructions (a Vector2) and apply them to the target horizontal and vertical rotation. The result is the familiar behaviour of being able to rotate around a subject, while rotating up and down within the clamped span.

There are several more camera behaviours in the project (which you should take a look at) and they are demonstrated in an example scene as well as within the presentation. However as a last example, I want to point out the TravelCamera component. Unlike the others, this does not inherit from CameraBehaviour – nor does it directly affect its rotation or position. In stead, it holds a simple piece of logic which enables and disables other behaviours, based on input activity. The result should be a behaviour somewhere between that seen in Journey and that of the Assassins Creed games.

I tried to keep this post short, but I hope you still find this useful and decide to build on the system. In any case, here are direct links to the resources covered in the post:

New Gear
Unity, iOS, TeamCity, AppCenter
RAID0 NVMe on Ubuntu
A Change of Gears
Unity Protocol Buffers
Behave 2.7
Behave 2.6
Trusted Gear
Mad Mash Versioning
Behave 2.5
Behave 2.4
The Engine Wars: Numbers
GDC 14: The Quest For Fun
Moving in Unity
Behave 2.3
Unity and .net assemblies
Behave 2.2
Behave 2.1
Behave 2.0
Unity Hacks: Dual sticks
Unity Hacks: Cameras
Unity Hacks: Touch gestures
Unite 13 video "Unity Hacks" available
The implicit local network interface
Talks and progress
Five years of Unity expertise looking for contracts
Automagic Unity Android Java gadget OF DOOM!
Invading Planet from your couch
Mountain Lion and laggy bluetooth and duct-tape
Unite 12 video and new videos section available
Asia Bootcamp videos now available
Path is now MIT licensed
Behave 1.4 released
So I've been a bit busy lately
Behave 1.3 released
IGDA Unity SIG slides
Second Unity IGDA SIG this evening: Scene construction and AI
First IGDA Unity SIG this evening
Alternative licensing available
Pathfinding in two lines
Path 2 released
Assembling and assimilating
Path 2 intro screencast
Path 2 beta release for GGJ
AIgameDev master class video now online
Expanding beta
Behave AIgameDev master class public stream
Behave master class on open AIgameDev stream tomorrow
Interview with AIGameDev
New video: From tree to code
Issue tracking on github Behave release project
IT University Copenhagen Unity course completed
IT University Copenhagen Unity course files Thursday
CPH IT University Unity course files
Behave 1.2 released
Video: Behave - starting from scratch
Behave runtime documentation updated
Behave 1.1 released
FAFF cleanup: Sketch
Building a menu of delegates and enums
Pick me! Pick me!
Optimising coroutine yielding in C#
Downloading the hydra
New license of Path: GPL
GUI drag-drop
Logging an entire GameObject
I bet you can't type an A!
Where did that component go?
New and improved: Behave 1.0 released
Behave 0.3b and unity 2.5
Behave 0.3b hotfix
Path tutorial video available
Path 1.0 launched!
Continued community tutorials
Community tutorial
New tutorial
First tutorial available
Behave 0.3b
unite '08 open-mic session
Behave 0.2b
Behave 0.1b
Behave pre-release
Path beta 0.3b
Path beta 0.2b
Path beta 0.1b
Path pre-release