Recently really busy, even the study of the time has not been, the original address: https://alastaira.wordpress.com/2013/11/08/smooth-unity-camera-transitions-with-animation-curves/
Put it in here first.
I ' m creating a game in which I want to transition between II camera Views–a Top-down, overhead camera that gives a zoom Ed-out world view, and an over-the-shoulder style forward-facing camera to give a close-up view. Let's say for the sake of discussion that these positions is defined relative to the player, as follows:
- Overview:position x/y/z: (0, 0). Rotation x/y/z: ( -90, 0, 0) (units above, rotated straight down)
- Close-up:position x/y/z: (0, 0,–0.5). Rotation x/y/z: (0, 0, 0) (0.5 units behind, aligned with player direction)
Rather than simply cut between the camera views, or present the Top-down view in a second minimap camera alongside the Main game view, I want to use a single camera and transition smoothly between the view locations. Initially, I tried to simply interpolate the position and rotation of the camera between the locations (using Lerp () F or linear interpolation of the position vectors and Slerp () for the rotation quaternions), based on a single zoom Paramete R:
transform.position = Vector3.Lerp(zoomstart.position, zoomend.position, zoom); transform.rotation = Quaternion.Slerp(zoomstart.rotation, zoomend.rotation, zoom); |
This gives:
However, this didn ' t create the effect I Wanted–i wanted to remain largely looking down as the camera zoomed in, and onl Y pull up to match that player's look vectors at relatively close zoom levels, and also to ease the movement at both ends O f the zoom.
My next thought is to ease in/out the camera motion using one of the functions described in this earlier post–perhaps a Sigmoid curve, so, the rate of rotation is greatest at either extreme of the zoom spectrum. But I had trouble finding a function, exactly described the motion I wanted to create.
And then I discovered Unity ' s animationcurves. I don ' t know why they ' re called animation curves, because they ' re not specific to animations @ all–they allow your to de Fine custom curves based on an arbitrary number of control points (keys), and then evaluate the value of the function at a NY point along the curve.
To look up the value of the along the curve use the Evaluate () method. For example, in the curve above, the Y value of the curve at x=0.5 are given by curve.evaluate (0.5), which results in 0.69 2. Using the can smoothly adjust any variable based on a single dimensional input.
Curves for Smooth Camera movement
I have three camera transform parameters the change between my II camera locations–the offset position in Y and Z axes , and the rotation in the X axis. Since each animation curve can express only one dimension, I thought I might need to create three animation Curves–one T o Describe each parameter this varies as the camera zooms in. However, on more thought I decided a better way:to has one curve to control the rotation around the x axis (i.e. adjusti Ng the pitch of the camera), and then a second curve to set the distance which the camera should is offset back based On the forward directionof the camera at the. Since the camera rotates about the x axis, translating back along it normal means that the second curve would govern both The height (y) and offset (z) in a single curve.
You can create animation curves in the inspector, but I initialised them in code as Follos:
public class CameraScript : MonoBehaviour {
// How camera pitch (i.e. rotation about x axis) should vary with zoom
public AnimationCurve pitchCurve;
// How far the camera should be placed back along the chosen pitch based on zoom
public AnimationCurve distanceCurve;
// Use this for initialization
void Start () {
// Create ‘S‘ shaped curve to adjust pitch
// Varies from 0 (looking forward) at 0, to 90 (looking straight down) at 1
pitchCurve = AnimationCurve.EaseInOut(0.0f, 0.0f, 1.0f, 90.0f);
// Create exponential shaped curve to adjust distance
// So zoom control will be more accurate at closer distances, and more coarse further away
Keyframe[] ks = new Keyframe[2];
// At zoom=0, offset by 0.5 units
ks[0] = new Keyframe(0, 0.5f);
ks[0].outTangent = 0;
// At zoom=1, offset by 60 units
ks[1] = new Keyframe(1, 60);
ks[1].inTangent = 90;
distanceCurve = new AnimationCurve(ks);
}
}
|
This generates the following curves:
I then evaluate the appropriate point from each curve based to the camera zoom level, as follows:
// Calculate the appropriate pitch (x rotation) for the camera based on current zoom
float targetRotX = pitchCurve.Evaluate(zoom);
// The desired yaw (y rotation) is to match that of the target object
float targetRotY = target.rotation.eulerAngles.y;
// Create target rotation as quaternion
// Set z to 0 as we don‘t want to roll the camera
Quaternion targetRot = Quaternion.Euler(targetRotX, targetRotY, 0.0f);
// Calculate in world-aligned axis, how far back we want the camera to be based on current zoom
Vector3 offset = Vector3.forward * distanceCurve.Evaluate(zoom);
// Then subtract this offset based on the current camera rotation
Vector3 targetPos = target.position - targetRot * offset;
|
Finally, rather than setting the camera position/rotation directly, I lerp/slerp between the current Transform.position/ro Tation towards the target position/rotation to smooth the movement and get the result as follows, which I ' m pretty happy W ITH (scene view on the left, resulting camera view in the right):
Turn a Unity camera animation control