Unity camera follows an object

Features:
Customizable settings: the distance between the camera and the target being followed, the speed of moving to the target position, and the offset angle from the target position. Switch tracking target.

Insert picture description here

using UnityEngine;
using System.Collections.Generic;

namespace Ceto
{
    
    
    public class CameraFlowTarget : MonoBehaviour
    {
    
    
        struct Position
        {
    
    
            public Vector3 forwardAmount;
            public float turnAmount;
            public Vector3 camRotation;
            public float camDistance;
        }
        public List<GameObject> obj = new List<GameObject>();
        public bool disableInterpolation;
        public GameObject m_ship;
        public Vector3 m_forward = new Vector3(0, 0, 1);
        public float m_shipMoveSpeed = 20.0f;

        [Range(0.01f, 1.0f)]
        public float shipSmoothness = 0.5f;
        public float m_camRotationSpeed = 10.0f;
        public float m_camStartRotationX = 10.0f;
        public float m_camStartRotationY = 60.0f;
        public float m_camStartRotationZ = 60.0f;
        //跟目标点保持的距离
        public float m_camStartDistance = 200.0f;

        [Range(0.01f, 1.0f)]
        public float camSmoothness = 0.5f;
        Position m_position, m_target;
        const float MAX_ACCELERATION = 1.0f;
        const float ACCELERATION_RATE = 1.0f;
        const float DECELERATION_RATE = 0.25f;
        float m_acceleration = 0.0f;
        public GameObject target;
        Vector3 m_previousPos, m_velocity;
        public GameObject m_dummy;

        GameObject Ship
        {
    
    
            get
            {
    
    
                if (m_ship == null)
                {
    
    
                    m_dummy = new GameObject();
                    m_ship = m_dummy;
                }
                return m_ship;
            }
            set
            {
    
    
                m_ship = value;
            }
        }

        void Start()
        {
    
    
            TheForward();
        }

        void TheForward()
        {
    
    
            m_position.camRotation.x = m_camStartRotationX;
            m_position.camRotation.y = m_camStartRotationY;
            m_position.camRotation.z = m_camStartRotationZ;
            m_position.camDistance = m_camStartDistance;
            m_position.forwardAmount = Vector3.zero;
            m_target = m_position;
        }

        void LateUpdate()
        {
    
    
            //if (是否可通过拖拽鼠标控制视角变化)
            //{
    
    
                ProcessInput();
            //}

            InterpolateToTarget();

            //if (不是第一人称视角)
            //{
    
    
                MoveShip();
            //}

            CameraChange();

            //**实时测试相机与目标点的距离,角度偏移等**
            //TheForward();
        }

      
        void MoveShip()
        {
    
    
            Vector3 eulerAngles = Ship.transform.eulerAngles;
            eulerAngles.y += m_position.turnAmount;
            Ship.transform.eulerAngles = eulerAngles;

            float ct = Mathf.Cos(m_position.camRotation.y * Mathf.Deg2Rad);
            float st = Mathf.Sin(m_position.camRotation.y * Mathf.Deg2Rad);
            float cp = Mathf.Cos(m_position.camRotation.x * Mathf.Deg2Rad);
            float sp = Mathf.Sin(m_position.camRotation.x * Mathf.Deg2Rad);

            Vector3 lookAt = Ship.transform.position;
            Vector3 pos = lookAt + (new Vector3(sp * st, ct, cp * st)) * m_position.camDistance;

            transform.position = pos;
            transform.LookAt(lookAt);

            m_velocity = Ship.transform.position - m_previousPos;
            m_previousPos = Ship.transform.position;

        }

        void InterpolateToTarget()
        {
    
    

            if (disableInterpolation || Time.timeScale == 0.0f)
            {
    
    
                m_position = m_target;
                return;
            }
            float smoothness;
            smoothness = 1.0f / Mathf.Clamp(camSmoothness, 0.01f, 1.0f);
            float camLerp = Mathf.Clamp01(Time.deltaTime * smoothness);
            m_position.camDistance = Mathf.Lerp(m_position.camDistance, m_target.camDistance, camLerp);
            m_position.camRotation = Vector2.Lerp(m_position.camRotation, m_target.camRotation, camLerp);

            //smoothness = 1.0f / Mathf.Clamp(shipSmoothness, 0.01f, 1.0f);
            //float shipLerp = Mathf.Clamp01(Time.deltaTime * smoothness);
            //m_position.forwardAmount = Vector3.Lerp(m_position.forwardAmount, m_target.forwardAmount, shipLerp);
            //m_position.turnAmount = Mathf.Lerp(m_position.turnAmount, m_target.turnAmount, shipLerp);
        }

        void ProcessInput()
        {
    
    
            float speed = m_shipMoveSpeed;
            float velocity = m_velocity.magnitude;

            m_target.forwardAmount = Vector3.zero;
            m_target.turnAmount = 0.0f;


            m_acceleration = Mathf.Clamp(m_acceleration, 0.0f, MAX_ACCELERATION);

            float dt = Time.deltaTime * 2000.0f;
            float amount = Mathf.Pow(1.02f, Mathf.Min(dt, 1.0f));

            if (Input.GetAxis("Mouse ScrollWheel") < 0.0f)
            {
    
    
                m_target.camDistance *= amount;
            }

            else if (Input.GetAxis("Mouse ScrollWheel") > 0.0f)
            {
    
    
                m_target.camDistance /= amount;
            }
            m_target.camDistance = Mathf.Max(1.0f, m_target.camDistance);
            //相机旋转角度范围设置
            m_target.camRotation.y = Mathf.Clamp(m_target.camRotation.y, 20.0f, 140.0f);

            if (Input.GetMouseButton(0))
            {
    
    
                m_target.camRotation.y += Input.GetAxis("Mouse Y") * m_camRotationSpeed;
                m_target.camRotation.x += Input.GetAxis("Mouse X") * m_camRotationSpeed;
            }

        }
        public void CameraChange()
        {
    
    
            if (Input.GetKey("1"))
            {
    
    
                m_ship = obj[0];
            }
            if (Input.GetKey("2"))
            {
    
    
                m_ship = obj[1];
            }
        }

        //视角切换 (镜头缓慢移动)
        public void SwitchtoF16(int i, float camDis, float camrot)
        {
    
    
            m_ship = obj[i];
            m_target.camDistance = camDis;
            m_target.camRotation.x = camrot;
        }

        /// <summary>
        /// 视角切换(镜头快速切换)
        /// </summary>
        /// <param name="i">被跟随物体的序号</param>
        /// <param name="camDis">相机与被跟随物体的距离</param>
        /// <param name="camrx">相机与被跟随物体的夹角</param>
        /// <param name="camry">相机与被跟随物体高度差</param>
        public void SwitchtoMainview(int i, float camDis, float camrx, float camry)
        {
    
    
            m_ship = obj[i];
            m_target.camDistance = camDis;
            m_target.camRotation.x = camrx;
            m_target.camRotation.y = camry;
            m_position.camDistance = Mathf.Lerp(m_position.camDistance, m_target.camDistance, 1);
            m_position.camRotation = Vector2.Lerp(m_position.camRotation, m_target.camRotation, 1);
        }

        void OnDestroy()
        {
    
    
            if (m_dummy != null)
                DestroyImmediate(m_dummy);
        }
    }

}

Guess you like

Origin blog.csdn.net/qq_22975451/article/details/113347308