1
\$\begingroup\$

I have implemented a follow camera in Unity 3D. However, if the player object rotates, the camera does not rotate with it. To fix this I used RotateAround as follows:

playerRotation = CastPositive(player.EulerAngles.y) //guarantees 0-360
cameraRotation = CastPositive(transform.EulerAngles.y)
difference = playerRotation - cameraRotation
transform.RotateAround(player.position, Vector3.up, difference * time.deltaTime)

This works in general. However at some point the difference snaps from -50 to 210. When this happens, the camera swings in the opposite direction all the way round the player object, instead of continuing on its orbit.

How can I avoid this value jump?

  • I've tried clamping the various values to no avail, but maybe I've missed something?
  • Quaternions?
\$\endgroup\$
3
\$\begingroup\$

I don't know which is the specific error in your case, but at least from my experience, I'd use quaternion instead. You can just lerp between your current camera rotation and the desired one. Something like:

transform.rotation = Quaternion.Lerp(transform.rotation, player.transform.rotation,Time.deltaTime * speed);

In general quaternions offer a simple and natural way to interpolate rotations, preventing problems like gimbal lock.

|improve this answer|||||
\$\endgroup\$
0
\$\begingroup\$

Code provided by Katherine Rix:

// Position camera to follow behind player's head.
private void Follow(){

    // orientation as an angle when projected onto the XZ plane
    // this functionality is modularise into a separate method because
    // I use it elsewhere
    float playerAngle = AngleOnXZPlane (player);
    float cameraAngle = AngleOnXZPlane (transform);

    // difference in orientations
    float rotationDiff = Mathf.DeltaAngle(cameraAngle, playerAngle);

    // rotate around target by time-sensitive difference between these angles
    transform.RotateAround(GetTarget(), Vector3.up, rotationDiff * Time.deltaTime);
}

// Find the angle made when projecting the rotation onto the xz plane.
// You could pass in the rotation as a parameter instead of the transform.
private float AngleOnXZPlane(Transform item){

    // get rotation as vector (relative to parent)
    Vector3 direction = item.rotation * item.parent.forward;

    // return angle in degrees when projected onto xz plane
    return Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
}
|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.