首页 > 代码库 > 一个摄像机控制类的总结

一个摄像机控制类的总结

一个摄像机控制类的总结


实现功能:

        通过鼠标的操纵,控制摄像机环绕模型对象旋转,从而进行对模型对象的观察。

 

设计思路:

        首先根据摄像机的当前方位,计算它应该到达的目标方位;

        然后通过插值运算,将摄像机逐帧移动到该目标方位。

 

过程描述:

1、 计算摄像机的目标方位。

 

        先计算摄像机本地坐标系轴向与世界坐标系轴向的夹角,作为方位的初始值。注意,这里只取摄像机需要旋转变化的坐标轴即可,这里我们用的是X和Y轴。

 

        在鼠标的控制过程中,实时的修改此夹角值。

 

        对修改后的夹角值进行限位处理,使之满足我们的需要。

 

        将限位处理后的夹角值由欧拉角的表示形式转换到四元数的表示形式,作为摄像机的目标方位保存。

      

2、 通过在摄像机的当前方位与目标方位间做插值运算,以一定的速度将摄像机向目标方位移动。

 

源代码:绑定在摄像机对象之上

      

    ///<summary>

    ///旋转轴的变换组件(模型对象)

    ///</summary>

    public Transform _tfmRotAxis;

    ///<summary>

    ///摄像机的移动缓冲

    ///</summary>

    public float _fZoomDmp = 5f;

    ///<summary>

    ///摄像机的移动速度

    ///</summary>

    public float _fZoomRate = 240f;

    ///<summary>

    ///鼠标X方向移动灵敏度

    ///</summary>

    public float _fXSpe = 6f;

    ///<summary>

    ///鼠标Y方向移动灵敏度

    ///</summary>

    public float _fYSpe = 6f;

    ///<summary>

    ///鼠标X方向最小角度限位

    ///</summary>

    public float _fMinLimitX = -360f;

    ///<summary>

    ///鼠标X方向最大角度限位

    ///</summary>

    public float _fMaxLimitX = 360f;

    ///<summary>

    ///鼠标Y方向最小角度限位

    ///</summary>

    public float _fMinLimitY = -360f;

    ///<summary>

    ///鼠标Y方向最大角度限位

    ///</summary>

    public float _fMaxLimitY = 360f;

    ///<summary>

    ///摄像机距旋转轴的最近距离

    ///</summary>

    public float _fMinDist = 0f;

    ///<summary>

    ///摄像机距旋转轴的最远距离

    ///</summary>

    public float _fMaxDist = 20f;

    ///<summary>

    ///移动的偏移量

    ///</summary>

    public Vector3 _vec3TarOffset;

//------------------------------ Private ----------------------------------

    ///<summary>

    ///摄像机的变换组件

    ///</summary>

    private Transform _tfmThis;

    ///<summary>

    ///摄像机到旋转轴的当前距离

    ///</summary>

    private float _fCurtDist;

    ///<summary>

    ///摄像机到旋转轴的目标距离

    ///</summary>

    private float _fTarDist;

    ///<summary>

    ///摄像机的目标朝向(方位)

    ///</summary>

    private Quaternion _quaTarRtn;

    ///<summary>

    ///摄像机X轴与世界坐标X轴的夹角

    ///</summary>

    private float _fXDgre;

    ///<summary>

    ///摄像机Y轴与世界坐标Y轴的夹角

    ///</summary>

    private float _fYDgre;

 

void Awake()

    {

        // cache

        _tfmThis = transform;

 

        _fCurtDist = Vector3.Distance(_tfmThis.position, _tfmRotAxis.position );

        _fTarDist = _fCurtDist;

 

        // 在世界坐标系之下,计算摄像机本地坐标系各坐标轴

        // 与世界坐标系各坐标轴的夹角

        _fXDgre = Vector3.Angle(Vector3.right, _tfmThis.right );// X轴夹角

        _fYDgre = Vector3.Angle(Vector3.up, _tfmThis.up );// Y轴夹角

    }

 

    void LateUpdate()

    {

        // 检测鼠标右键按下

        if ( Input.GetMouseButton( 1 ) ) {

 

            // 计算当前的轴向夹角

            _fXDgre += Input.GetAxis("Mouse X" ) * _fXSpe;

            _fYDgre -= Input.GetAxis("Mouse Y" ) * _fYSpe;

            // 对夹角进行限位处理

            _fXDgre = Mathf.Clamp(_fXDgre, _fMinLimitX, _fMaxLimitX );

            _fYDgre = Mathf.Clamp(_fYDgre, _fMinLimitY, _fMaxLimitY );

            // 计算目标朝向(方位)

            _quaTarRtn = Quaternion.Euler( _fYDgre, _fXDgre, 0 );

            // 插值运算

            _tfmThis.rotation = Quaternion.Lerp( _tfmThis.rotation, _quaTarRtn,_fZoomDmp *Time.deltaTime );

        }

 

        ScrollWheelCtrl();

    }


    ///<summary>

    ///鼠标滚轮控制视野的缩放

    ///</summary>

    private void ScrollWheelCtrl()

    {

        _fTarDist -= Input.GetAxis("Mouse ScrollWheel" ) * _fZoomRate*Time.deltaTime;

 

        _fTarDist = Mathf.Clamp(_fTarDist, _fMinDist, _fMaxDist );

 

        _fCurtDist = Mathf.Lerp(_fCurtDist, _fTarDist, _fZoomDmp *Time.deltaTime);

 

        _tfmThis.position =_tfmRotAxis.position - ( _tfmThis.rotation *Vector3.forward* _fCurtDist + _vec3TarOffset );

    }