第三人称相机

using UnityEngine;

public class PlayerCamera3rd : MonoBehaviour 
{
    Vector3 m_defaultDir;
    Transform m_PlayerTransform;
    Vector3 m_RotateValue;
    Vector3 m_PitchRotateAxis;  //俯仰方向轴
    Vector3 m_YawRotateAxis;//左右横向旋转轴


    public float distance = 4;
    public float speed = 120f;
    public Vector3 offest = new Vector3(0, 1.5f, 0);
    public float followRange = 0.5f;
    Vector3 followPoint;

    //翻转pitch方向相机旋转 
    public bool invertPitch;
    public Vector2 pitchLimit = new Vector2(-40f,85f);

    //修改相机位置缓动
    float m_CurrentDistance;
    float m_DistanceRecoveryDelayCounter;
    public float distanceRecoverySpeed = 4f;
    public float distanceRecoveryDelay = 0.3f;

    public Transform followPlayer;

    Vector3 upAxis;
    void OnEnable()
    {
        if (followPlayer == null)
        {
            m_PlayerTransform = GameObject.FindGameObjectWithTag("Player").transform;
        }
        else
            m_PlayerTransform = followPlayer;
        followPoint = m_PlayerTransform.position;
         upAxis = -Physics.gravity.normalized;
        m_defaultDir = Vector3.ProjectOnPlane((transform.position - m_PlayerTransform.position), upAxis).normalized;
        
        m_YawRotateAxis = upAxis;


    }

    void LateUpdate()
    {
        Vector2 inputDelta = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
        m_RotateValue.x += inputDelta.x * speed * Time.smoothDeltaTime;
        m_RotateValue.x = AngleCorrection(m_RotateValue.x);

        m_RotateValue.y += inputDelta.y * speed * (invertPitch ? -1 : 1) * Time.smoothDeltaTime;
        m_RotateValue.y = AngleCorrection(m_RotateValue.y);

        m_RotateValue.y = Mathf.Clamp(m_RotateValue.y, pitchLimit.x, pitchLimit.y);

        var horizontalQuat = Quaternion.AngleAxis(m_RotateValue.x, m_YawRotateAxis);
        m_PitchRotateAxis = Vector3.Cross(upAxis, Vector3.ProjectOnPlane(transform.forward, upAxis));
        var verticalQuat = Quaternion.AngleAxis(m_RotateValue.y, m_PitchRotateAxis);

        var finalDir = horizontalQuat * verticalQuat * m_defaultDir;
        var from = m_PlayerTransform.localToWorldMatrix.MultiplyPoint3x4(offest);
        var to = from + finalDir * distance;
        var exceptTo = ObstacleProcess(from, to);

        var expectDistance = Vector3.Distance(exceptTo, from);

        followPoint= UpdateFocusPoint(m_PlayerTransform,followRange);
        m_CurrentDistance = (followPoint - transform.position).magnitude;

        //Debug.Log(m_CurrentDistance);
        if (expectDistance < m_CurrentDistance)
        {
            m_CurrentDistance = expectDistance;
            m_DistanceRecoveryDelayCounter = distanceRecoveryDelay;

        }
        else
        {
            if (m_DistanceRecoveryDelayCounter > 0f)
                m_DistanceRecoveryDelayCounter -= Time.deltaTime;
            else
            {
                m_CurrentDistance = Mathf.Lerp(m_CurrentDistance, expectDistance, Time.smoothDeltaTime * distanceRecoverySpeed);
            }
        }
        transform.position = Vector3.Slerp(transform.position,from + finalDir * m_CurrentDistance,Time.deltaTime* distanceRecoverySpeed);
        transform.LookAt(from);
    }
    /// <summary>
    /// 更新相机跟随点位置
    /// </summary>
    /// <param name="m_PlayerTransform"></param>
    /// <param name="followRange"></param>
    /// <returns></returns>
    Vector3 UpdateFocusPoint(Transform m_PlayerTransform,float followRange)
    {
        Vector3 followPoint = m_PlayerTransform.position;
        if (followRange>0)
        {
            if ((m_PlayerTransform.position - followPoint).magnitude > followRange)
            {
                followPoint = Vector3.Slerp(followPoint, m_PlayerTransform.position, Time.deltaTime * distanceRecoverySpeed);
            }
            
        }
        else
        {
            followPoint = m_PlayerTransform.position;
        }
        return followPoint;
    }
    float AngleCorrection(float value)
    {
        if (value > 180f) return m_RotateValue.x - 360f;
        else if (value < -180f) return m_RotateValue.x + 360f;
        return value;
    }
    public LayerMask obstacleLayerMask; 
    public float obstacleSphereRadius = 0.3f;  
   
    Vector3 ObstacleProcess(Vector3 from,Vector3 to)
    {
        var dir = (to - from).normalized;
        var hit = default(RaycastHit);
        var isHit = Physics.SphereCast(new Ray(from, dir), obstacleSphereRadius, out hit, distance, obstacleLayerMask);
        if (isHit)
        {
            return hit.point + (-dir * obstacleSphereRadius);
        }
        return to; 
    }
}

 

posted @ 2021-01-28 17:25  wsfw  阅读(99)  评论(0编辑  收藏  举报