二、功能开发阶段-2-相机的控制(版本_V1.0)

前言:
相机的控制是一个比较复杂的过程,尤其是在3D游戏中。Unity的资源商店里有很多摄像机插件,我也使用过。但是因为大部分都封装了代码,看不到里面的内容,那么有时候想修改功能却不是很方便。
这里我将逐步的完成摄像机的控制,这个是初始版本,我会在将来逐步完成相机的功能。

一、摄像机的结构
1.相机的移动
2.相机的旋转
3.相机的缩放
4.真正相机的位置

a.首先创建一个空物体,并且命名为:“CameraFallow”。
b.在CameraFallow物体下,创建空物体,并且命名为:“CameraRotationY”。
c.在CameraRotationY物体下,创建空物体,并且命名为:“CameraRotationX”;
d.在CameraRotationX物体下,创建空物体,并且命名为:“CameraZoom”;
e.在CameraZoom物体下,创建空物体,并且命名为:“CameraContainer”;
f.在CameraContainer物体下,将我们的相机拖到它的下面,作为子物体。其最终结构图如下:
在这里插入图片描述
解释:
CameraFallow负责跟随角色
CameraRotationY负责绕Y轴旋转
CameraRotationX负责绕X轴旋转
CameraZoom负责缩放功能
CameraContainer是相机的容器
Main Camera是真正的相机

二、相机的脚本
1.创建代码“CameraCtrl.cs”,并且挂载到CameraFallow上。
2.具体的代码如下:

public class CameraCtrl : MonoSingleton<CameraCtrl>
{
    /// <summary>
    /// 相机的旋转X轴
    /// </summary>
    private Transform m_CameraRotationX;

    /// <summary>
    /// 相机的旋转Y轴
    /// </summary>
    public Transform CameraRotationY;

    /// <summary>
    /// 相机的缩放
    /// </summary>
    private Transform m_CameraZoom;

    /// <summary>
    /// 相机的容器
    /// </summary>
    private Transform m_CameraContainer;

    /// <summary>
    /// 围绕Y的旋转的时候,鼠标X方向的增量
    /// </summary>
    [SerializeField]
    public float m_XSensitivity = 1.0f;

    /// <summary>
    /// 围绕X轴旋转的时候,鼠标Y轴方向的增量
    /// </summary>
    [SerializeField]
    private float m_YSensitivity = 1.0f;

    /// <summary>
    /// 是否限制围绕X轴旋转
    /// </summary>
    [SerializeField]
    private bool m_ClampVerticalRotation = true;

    /// <summary>
    /// X轴旋转的最小值
    /// </summary>
    [SerializeField]
    private float m_MinimumX = -90F;

    /// <summary>
    /// X轴旋转的最大值
    /// </summary>
    [SerializeField]
    private float m_MaximumX = 90F;

    /// <summary>
    /// 是否平滑过渡
    /// </summary>
    [SerializeField]
    private bool m_Smooth;

    /// <summary>
    /// 平滑过渡时间
    /// </summary>
    [SerializeField]
    private float m_SmoothTime = 5.0f;

    /// <summary>
    /// 相机缩放的速度
    /// </summary>
    [SerializeField]
    private float m_ZoomSpeed = 5.0f;

    /// <summary>
    /// 相机近距离
    /// </summary>
    [SerializeField]
    private float m_ZoomNear = -2.0f;

    /// <summary>
    /// 相机最远距离
    /// </summary>
    [SerializeField]
    private float m_ZoomFar = -6.0f;

    /// <summary>
    /// 相机m_CameraRotationX的本地旋转值
    /// </summary>
    private Quaternion m_CameraTargetRotX;

    /// <summary>
    /// 相机m_CameraRotationY的本地旋转值
    /// </summary>
    private Quaternion m_CameraTargetRotY;

    /// <summary>
    /// 相机缩放目标位置
    /// </summary>
    private Vector3 m_CameraTargetZoomPos;

    private Transform m_Player;

    /// <summary>
    /// 相机的高度
    /// </summary>
    [SerializeField]
    private Vector3 m_CameraHight = new Vector3(0.0f, 1.5f, 0.0f);

    [SerializeField]
    private float m_CameraFollowSpeed = 1.0f;

    [SerializeField]
    private bool m_UseMouse;

    private void Awake()
    {
        CameraRotationY = transform.Find("CameraRotationY").transform;
        m_CameraRotationX = transform.Find("CameraRotationY/CameraRotationX").transform;
        m_CameraZoom = transform.Find("CameraRotationY/CameraRotationX/CameraZoom").transform;
        m_CameraContainer = transform.Find("CameraRotationY/CameraRotationX/CameraZoom/CameraContainer").transform;

        m_CameraTargetRotX = m_CameraRotationX.transform.localRotation;
        m_CameraTargetRotY = CameraRotationY.transform.localRotation;

        m_Player = GameObject.FindGameObjectWithTag("Player").transform;
    }

    private void Start()
    {      
        Init();    
    }

    /// <summary>
    /// 相机初始化
    /// </summary>
    public void Init()
    {
        m_CameraZoom.localPosition = new Vector3(0.0f, 0.0f, m_ZoomNear);
        m_UseMouse = false;
        Cursor.visible = m_UseMouse;
    }

    /// <summary>
    /// 相机跟随角色
    /// </summary>
    public void CameraAutoFollowPlayer()
    {
        transform.position = Vector3.Lerp(transform.position, m_Player.position + m_CameraHight, Time.deltaTime * m_CameraFollowSpeed);
    }

    /// <summary>
    /// 相机实时看着主角
    /// </summary>
    /// <param name="position"></param>
    private void CamaraAutoLookAtPlayer()
    {
        m_CameraContainer.LookAt(m_Player.position + m_CameraHight);
    }

    private void LateUpdate()
    {
        CameraAutoFollowPlayer();
        CamaraAutoLookAtPlayer();
        CameraZoom();

        if (!m_UseMouse)
        {
            RotateView();           
        }

        if (Input.GetKeyDown(KeyCode.Tab))
        {
            m_UseMouse = !m_UseMouse;
            Cursor.visible = m_UseMouse;
        }
    }

    private void RotateView()
    {
        float yRot = CrossPlatformInputManager.GetAxis("Mouse X") * m_XSensitivity;
        float xRot = CrossPlatformInputManager.GetAxis("Mouse Y") * m_YSensitivity;

        m_CameraTargetRotX *= Quaternion.Euler(-xRot, 0.0f, 0f);
        m_CameraTargetRotY *= Quaternion.Euler(0.0f, yRot, 0f);

        if (m_ClampVerticalRotation)
        {
            m_CameraTargetRotX = ClampRotationAroundAxis(m_CameraTargetRotX);
        }

        if (m_Smooth)
        {
            m_CameraRotationX.transform.localRotation = Quaternion.Slerp(m_CameraRotationX.transform.localRotation, m_CameraTargetRotX,
                m_SmoothTime * Time.deltaTime);

            CameraRotationY.transform.localRotation = Quaternion.Slerp(CameraRotationY.transform.localRotation, m_CameraTargetRotY,
                m_SmoothTime * Time.deltaTime);

        }
        else
        {
            m_CameraRotationX.transform.localRotation = m_CameraTargetRotX;
            CameraRotationY.transform.localRotation = m_CameraTargetRotY;
        }
    }

    private void CameraZoom()
    {
        if (Input.GetAxis("Mouse ScrollWheel") < 0.0f)
        {
            m_CameraTargetZoomPos = new Vector3(0.0f, 0.0f, m_CameraZoom.localPosition.z - 2.0f);
            m_CameraTargetZoomPos = ClampCameraZoom(m_CameraTargetZoomPos);
        }
        else if (Input.GetAxis("Mouse ScrollWheel") > 0.0f)
        {
            m_CameraTargetZoomPos = new Vector3(0.0f, 0.0f, m_CameraZoom.localPosition.z + 2.0f);
            m_CameraTargetZoomPos = ClampCameraZoom(m_CameraTargetZoomPos);
        }

        if (m_CameraTargetZoomPos != Vector3.zero)
        {
            m_CameraZoom.localPosition = Vector3.Lerp(m_CameraZoom.localPosition, m_CameraTargetZoomPos, m_ZoomSpeed * Time.deltaTime);
        }
    }

    /// <summary>
    /// 限制缩放摄像机的值
    /// </summary>
    /// <param name="pos"></param>
    /// <returns></returns>
    private Vector3 ClampCameraZoom(Vector3 pos)
    {
        float value = Mathf.Clamp(pos.z, m_ZoomFar, m_ZoomNear);
        return new Vector3(0, 0, value);
    }

    /// <summary>
    /// 限制X轴的旋转
    /// </summary>
    /// <param name="q"></param>
    /// <returns></returns>
    private Quaternion ClampRotationAroundAxis(Quaternion q)
    {
        q.x /= q.w;
        q.y /= q.w;
        q.z /= q.w;
        q.w = 1.0f;

        float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan(q.x);

        angleX = Mathf.Clamp(angleX, m_MinimumX, m_MaximumX);

        q.x = Mathf.Tan(0.5f * Mathf.Deg2Rad * angleX);

        return q;
    }
}

3.我的设置如下图:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Dean272727/article/details/88900262
今日推荐