Tuesday, April 22, 2014

Unity3D: Getting a Camera to Follow an Object with Smoothing

For use in my current prototype, Codename: Factions, I needed a system that would allow me to pass a gameobject to a function and then the camera would pan over to center that object on the screen regardless of it's location.  I wanted the transition to be smooth, efficient, and useful in any scenario.

My first thought was to use the gameobject I wanted to follow as the target, but before starting I could see some scoping issues arising in the future.  My solution was to create a simple cube, disable the Mesh Renderer and any other Components I didn't need, and set that as the object for the camera to follow.  To follow a character who was chopping a tree, for instance, I could simply parent the invisible cube to the character, and wallah, it appears as though the camera is following the character.  This makes things much easier to work with, since my code is as simple as "camera, follow the same object you've been following since the level loaded" rather than "hey try and follow this object, and if there's an error, try this, etc. etc."  Best to keep things simple.

Mesh Renderer for the Camera Target is disabled rather than removed, so it can be turned on at any time for debugging purposes.

With that done, next was the transition from the cameras current location to the desired location.  Again, keeping things simple, I created a container object for the camera, which allowed me to position the camera however I wanted while keeping it's container nicely located at Vector3(0, 0, 0).  Why was this important?  Well, it makes animating camera positions much easier in the long run, since while the camera moves within it's local space, the container itself will always be located in the same position as the invisible cube that it is following.  So, if you want to zoom down to the object and get an up-close-and-personal shot, it's as easy as adjusting the local transform vector of the camera itself... meanwhile it's parent's world position is still exactly where it needs to be.  Need the camera to zoom out?  Just subtract from it's current local z position.  Wallah.

A very simple camera heirarchy

Alright, so now I have a container with a nested camera and an object to follow.  If I wanted the camera to simply snap to the position I pass to the function, then I'm basically done.  But what I want is to pass a Vector3 to the function and have the camera automatically pan itself to that position.  Vector3.SmoothDamp to the rescue!

 Camera.main.transform.parent.position = Vector3.SmoothDamp (Camera.main.transform.parent.position, cameraTarget.position, ref _cameraVelocity, _cameraSmoothTime);  

If you're new to Unity, and have not played around with Smooth.Damp, or Lerping, or Slerping, I highly suggest you take the time to learn it.  It makes smooth movement between Vectors in Unity as simple as one line of code, and that's pretty much as good as you're ever going to have it.

1 comment:

  1. Tried that with my camera follow thing. I only wanted the camera to follow the player while moving, but not when jumping in the air. I didn't want the camera to jump *with* the player. And yeah, later on i found out that i could use that to make the camera go all over the place on a whim :P