Camera Rotate and Smooth

Hi Guys,

I am trying to get a smooth camera motion with my current camera script. I can get them to work separately but not together I have tried different methods but can’t seem to get it to work correctly

This is the Smooth follow script.

    public Transform target;

    public float smoothSpeed = 0.125f;
    public Vector3 offset;

    void FixedUpdate()
    {
        Vector3 desiredPosition = target.position + offset;
        Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
        transform.position = smoothedPosition;

        transform.LookAt(target);
    }

This is my main camera script.

public Transform target;

    public float rotateSpeed = 7;

    [Range(0.01f, 1.0f)]
    public float smoothSpeed = 0.5f;

    public Vector3 offset;

    void FixedUpdate()
    {
        float horizontal = Input.GetAxis("Mouse X") * rotateSpeed * Time.deltaTime;
        float verticle = Input.GetAxis("Mouse Y")  * rotateSpeed * Time.deltaTime;
        //You didn't use verticle before. Depending on your model/setup you might verticle as the 3rd (Z) parameter to get rotation in the right direction
        target.transform.Rotate(verticle, horizontal, 0);  //This line rotates the transform

        Vector3 desiredPosition = target.position + offset;
        Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
        
        // transform.position = smoothedPosition;

        float desiredAngle = target.transform.eulerAngles.y;

        Quaternion rotation = Quaternion.Euler(0, desiredAngle, verticle);
        transform.position = target.transform.position - (rotation * offset);

        //transform.position = Vector3.Slerp(transform.position, offset, SmoothFactor);

        transform.LookAt(target.transform); //This sets the absolute rotation of the transform. This call will "override" the above call to Rotate
    }

What would be the correct approach to get them both working?

Hi Jonathan,

Are both scripts attached to your camera? What did you expect to happen and what happened instead?

Hi,

Thanks for your reply. No there not both attached I’m trying to combine the 2 scripts because they both do what I want.

I am trying to get a fixed camera behind the player so if he turns so does the camera so in other words Its always facing the way he’s looking. Then if he walks or runs the camera will follow behind him and once he stops the camera catches up and goes back into position.

Right now the camera turns when the player turns. If I run the scripts separately they do what I want.

Couldn’t you simply parent the camera to the player?

using UnityEngine;
using System.Collections;

public class TestCamera : MonoBehaviour
{

    public Transform target;                            // Target to follow
    public float targetHeight = 1.7f;                       // Vertical offset adjustment
    public float distance = 12.0f;                          // Default Distance
    public float offsetFromWall = 0.1f;                     // Bring camera away from any colliding objects
    public float maxDistance = 20;                      // Maximum zoom Distance
    public float minDistance = 0.6f;                        // Minimum zoom Distance
    public float xSpeed = 200.0f;                           // Orbit speed (Left/Right)
    public float ySpeed = 200.0f;                           // Orbit speed (Up/Down)
    public float yMinLimit = -80;                           // Looking up limit
    public float yMaxLimit = 80;                            // Looking down limit
    public float zoomRate = 40;                             // Zoom Speed
    public float rotationDampening = 3.0f;              // Auto Rotation speed (higher = faster)
    public float zoomDampening = 5.0f;                  // Auto Zoom speed (Higher = faster)
    public float MaximumDegreesRot = 90f;
    LayerMask collisionLayers = -1;     // What the camera will collide with

//    public bool lockToRearOfTarget;
    public bool allowMouseInputX = true;
    public bool allowMouseInputY = true;

    private float xDeg = 0.0f;
    private float yDeg = 0.0f;
    private float currentDistance;
    public float desiredDistance;
    private float correctedDistance;
//    private bool rotateBehind; appearing not used

    public GameObject userModel;
    public bool inFirstPerson;
    Rigidbody myRigidbody = null;

    void Start()
    {

        Vector3 angles = transform.eulerAngles;
        xDeg = angles.x;
        yDeg = angles.y;
        currentDistance = distance;
        desiredDistance = distance;
        correctedDistance = distance;

        // Make the rigid body not change rotation
        if (myRigidbody)
            myRigidbody.freezeRotation = true;

        //if (lockToRearOfTarget)
        //    rotateBehind = true;
    }

    void Update()
    {

        if (Input.GetAxis("Mouse ScrollWheel") < 0)
        {

            if (inFirstPerson == true)
            {

                minDistance = 10;
                desiredDistance = 15;
                userModel.SetActive(true);
                inFirstPerson = false;
            }
        }

        if (desiredDistance == 10)
        {

            minDistance = 0;
            desiredDistance = 0;
            userModel.SetActive(false);
            inFirstPerson = true;
        }
    }

    //Only Move camera after everything else has been updated
    void LateUpdate()
    {

        // Don't do anything if target is not defined
        if (!target)
            return;

 //        Vector3 vTargetOffset3;

        // If either mouse buttons are down, let the mouse govern camera position
        if (GUIUtility.hotControl == 0)
        {
            if (Input.GetKey(KeyCode.LeftControl))
            {

            }
            else
            {
                if (Input.GetMouseButton(1))
                {
                    //Check to see if mouse input is allowed on the axis
                    if (allowMouseInputX)
                        xDeg += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
                    if (allowMouseInputY)
                        yDeg -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;

                }
            }
        }
        ClampAngle(yDeg);

        // Set camera rotation
        //Changed the below out to try to fix the camera rotation but produces leaning camera, May fix with Camera arm 
        //Quaternion rotation = Quaternion.Euler(yDeg, xDeg, 0);
        Quaternion targetRot = Quaternion.Euler(yDeg, xDeg, 0) * target.rotation;
        Quaternion rotation = Quaternion.RotateTowards(transform.rotation, targetRot, (float)MaximumDegreesRot);
        transform.rotation = rotation;

        // Calculate the desired distance
        desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
        desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
        correctedDistance = desiredDistance;

        // Calculate desired camera position
        Vector3 vTargetOffset = new Vector3(0, -targetHeight, 0);
        Vector3 position = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset);

        // Check for collision using the true target's desired registration point as set by user using height
        RaycastHit collisionHit;
        Vector3 trueTargetPosition = new Vector3(target.position.x, target.position.y + targetHeight, target.position.z);

        // If there was a collision, correct the camera position and calculate the corrected distance
        bool isCorrected = false;
        if (Physics.Linecast(trueTargetPosition, position, out collisionHit, collisionLayers))
        {
            correctedDistance = Vector3.Distance(trueTargetPosition, collisionHit.point) - offsetFromWall;
            isCorrected = true;
        }

        // For smoothing, lerp distance only if either distance wasn't corrected, or correctedDistance is more than currentDistance
        currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp(currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance;

        // Keep within limits
        currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);

        // Recalculate position based on the new currentDistance
        position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset);

        //Finally Set rotation and position of camera
        transform.rotation = rotation;
        transform.position = position;
    }

    void ClampAngle(float angle)
    {
        if (angle < -360)
            angle += 360;
        if (angle > 360)
            angle -= 360;

        yDeg = Mathf.Clamp(angle, -60, 80);
    }

}

I think thats the one i was using in my RPG bit this should help you compare. WARNING its a little buggy as if you rotate the player the camera doesnt lock to the rear of the target.

This is assuming you ar ein 3d

You could extract them into different methods and call them from your FixedUpdate(), so that it moves first, then rotates, and then put your LookAt into a third method and call it after the other two. That’s what I ended up doing with my camera.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms