美文网首页
Unity旋转和缩放02-控制摄像机

Unity旋转和缩放02-控制摄像机

作者: 玄策丶 | 来源:发表于2020-03-31 15:05 被阅读0次

    Unity旋转和缩放01-控制模型自身

    PC端:控制摄像机,围绕模型旋转实现旋转效果、与模型的距离实现缩放效果。功能实现:Unity 的Scene视图控制效果

    0、Utils

    using UnityEngine;
    namespace Utils
    {
        public static class Math
        {
            public static bool IsEqual(float a, float b)
            {
                if (Mathf.Abs(a - b) < 0.000001f)
                {
                    return true;
                }
                return false;
            }
    
            public static Matrix4x4 MatrixLerp(Matrix4x4 from, Matrix4x4 to, float t)
            {
                t = Mathf.Clamp01(t);
                Matrix4x4 lerpMatrix = new Matrix4x4();
                for (int i = 0; i < 4; i++)
                {
                    lerpMatrix.SetRow(i, Vector4.Lerp(from.GetRow(i), to.GetRow(i), t));
                }
                return lerpMatrix;
            }
            /// <summary>
            /// 对角度进行限制.
            /// </summary>
            public static float ClampAngle(float angle, float min, float max)
            {
                if (angle < -360)
                    angle += 360;
                if (angle > 360)
                    angle -= 360;
                return Mathf.Clamp(angle, min, max);
            }
        }
    }
    

    1、CameraController 挂载摄像机上

    using UnityEngine;
    using System.Collections;
    
    public class CameraController : MonoBehaviour
    {
        /// <summary>
        /// 视角类型.
        /// </summary>
        private enum ViewType
        {
            _2D = 0,
            _3D
        }
    
        /// <summary>
        /// 鼠标按键.
        /// </summary>
        private enum MouseButton
        {
            /// <summary>
            /// 鼠标左键.
            /// </summary>
            LEFT = 0,
            /// <summary>
            /// 鼠标右键.
            /// </summary> 
            RIGHT,
            /// <summary>
            /// 鼠标中键.
            /// </summary>
            MIDDLE
        }
    
        /// <summary>
        /// 指针样式.
        /// </summary>
        private enum CursorType
        {
            /// <summary>
            /// 默认样式.
            /// </summary>
            DEFAULT = 0,
            /// <summary>
            /// 小手.
            /// </summary>
            HAND,
            /// <summary>
            /// 眼睛.
            /// </summary>
            EYE,
            /// <summary>
            /// 放大镜.
            /// </summary>
            MAGNIFIER
        }
    
        #region 字段
        private const string MOUSESCROLLWHEEL = "Mouse ScrollWheel";        // 鼠标滚轮.
        private const string MOUSEX = "Mouse X";
        private const string MOUSEY = "Mouse Y";
    
        #region 输入
    
        private bool leftAltKeyDown;                                        // 左Alt键-按下.
        private bool rightAltKeyDown;                                       // 右Alt键-按下.
        private bool leftAltKey;                                            // 左Alt键-长按.
        private bool rightAltKey;                                           // 右Alt键-长按.
        private bool leftAltKeyUp;                                          // 左Alt键-抬起.
        private bool rightAltKeyUp;                                         // 右Alt键-抬起.
        private bool leftMouseButtonDown;                                   // 鼠标左键-按下.
        private bool rightMouseButtonDown;                                  // 鼠标右键-按下.
        private bool leftMouseButton;                                       // 鼠标左键-长按.
        private bool rightMouseButton;                                      // 鼠标右键-长按.
        private bool rightMouseButtonUp;                                    // 鼠标右键-抬起.
        private bool middleMouseButton;                                     // 鼠标中键-长按.
        private bool middleMouseButtonUp;                                   // 鼠标中键-抬起.
    
        #endregion
    
        private Camera m_Camera;                                            // 相机.
        private Texture2D handCursorTexture;                                // 小手.
        private Texture2D eyeCursorTexture;                                 // 眼睛.
        private Texture2D magnifierCursorTexture;                           // 放大镜.
    
        private Vector2 hotSpot = Vector2.zero;
        private CursorMode cursorMode = CursorMode.Auto;
    
        private float angle_X;                                              // 水平方向的角度值,绕Transform的y轴旋转(左右)
        private float angle_Y;                                              // 竖直方向的角度值,绕Transform的x轴旋转(上下)
        private float angle_Z;
    
        // 切换视角
        private Matrix4x4 defaultOrthProjMat;                               // 相机默认的正交投影矩阵.
        private Matrix4x4 defaultPersProjMat;                               // 相机默认的透视投影矩阵.
        private Matrix4x4 currentProjMat;                                   // 相机当前的投影矩阵.
        private bool isChangingViewType = false;                            // 正在切换视角.
        private float viewTypeLerpTime = 0f;                                // 插值时间.
        private ViewType viewType;                                          // 当前视角.
    
        [Header("Zoom")]
        // 相机拉近拉远 Zoom
        [SerializeField]
        private float distance = 20f;                      // 相机与lookAroudPos点的距离.
        [SerializeField, Range(1f, 20f)]
        private float zoomSpeed = 10f;                                      // 滚轮缩放速度.
        [SerializeField]
        private float maxDistance = 100f;                  // 相机最远距离.
        [SerializeField]
        private float minDistance = 1f;                    // 相机最近距离.
    
        [Header("360° Rotate")]
        // Alt+鼠标拖动, 360度观察
        [SerializeField, Range(2f, 10f)]
        private float rotateSensitivity = 5f;                               // 旋转灵敏度.
        private Vector3 lookAroundPos = Vector3.zero;
    
        // Alt+鼠标右键 放大缩小
        [Header("Field Of View")]
        private float minFov = 20f;                                         // 最小视角.
        private float maxFov = 135f;                                        // 最大视角.
        private Vector3 lastMousePosFov = Vector3.zero;
        [SerializeField, Range(0.01f, 0.1f)]
        private float fovSensitivity = 0.05f;                               // 视角灵敏度.
    
        // 选中物体聚焦
        private GameObject selectedObj = null;                              // 选中的物体.
        private float raycastMaxDistance = 1000f;
        private LayerMask raycastLayerMask;
        private RaycastHit raycastHit;
    
        [Header("Focus")]
        [SerializeField, Range(0.1f, 5f)]
        private float focusSpeed = 3.0f;                                    // 聚焦的速度.
        [SerializeField]
        private float focusDistance = 3f;                                   // 聚焦时与物体的距离.
        private bool isFocusing = false;                                    // 相机正看向物体中.
        private float focusTime = 0f;                                       // 聚焦时间.
        private Vector3 cameraInitForward;                                  // 相机最初的前方.
        private Vector3 focusTargetForward;                                 // 聚焦目标前方.
        private Vector3 focusInitPos;                                       // 聚焦前相机初始位置.
        private Vector3 focusTargetPos;                                     // 聚焦目标位置.
        #endregion
    
        private Vector3 MouseDownPos; //旋转摄像机位置不变
        #region Unity_Method
    
        private void Start()
        {
            Init();
        }
    
        private void Update()
        {
            Debug.Log(Camera.main.transform.eulerAngles);
        }
        private void LateUpdate()
        {
            // 更新输入.
            UpdateInput();
            // 切换视角.
            SwitchViewType();
            // 拉近拉远.
            Zoom();
            // 拖动相机.
            Drag();
            // 360°查看.
            LookAround();
            // 放大缩小. 和切换视角共同使用时有Bug.
            Magnifier();
            // 聚焦.
            Focus();
            //wasd移动
            wasdMove();
            //旋转摄像机位置不变
            //RoCam();
            //限制旋转角度
        }
    
    
    
        //private void OnGUI()
        //{
        //    if (GUI.Button(new Rect(Vector2.zero, new Vector2(100, 50)), "正交"))
        //    {
        //        SetViewType(ViewType._2D);
        //    }
    
        //    if (GUI.Button(new Rect(Vector2.up * 60, new Vector2(100, 50)), "透视"))
        //    {
        //        SetViewType(ViewType._3D);
        //    }
    
        //    if (GUI.Button(new Rect(Vector2.up * 120, new Vector2(100, 50)), "正视图"))
        //    {
        //        Front();
        //    }
    
        //    if (GUI.Button(new Rect(Vector2.up * 180, new Vector2(100, 50)), "后视图"))
        //    {
        //        Back();
        //    }
    
        //    if (GUI.Button(new Rect(Vector2.up * 240, new Vector2(100, 50)), "左视图"))
        //    {
        //        Left();
        //    }
    
        //    if (GUI.Button(new Rect(Vector2.up * 300, new Vector2(100, 50)), "右视图"))
        //    {
        //        Right();
        //    }
    
        //    if (GUI.Button(new Rect(Vector2.up * 360, new Vector2(100, 50)), "上视图"))
        //    {
        //        Top();
        //    }
    
        //    if (GUI.Button(new Rect(Vector2.up * 420, new Vector2(100, 50)), "下视图"))
        //    {
        //        Down();
        //    }
        //}
    
        #endregion
    
        #region 初始化相关
    
        /// <summary>
        /// 初始化.
        /// </summary>
        private void Init()
        {
            m_Camera = GetComponent<Camera>();
            raycastLayerMask = 1 << LayerMask.NameToLayer("Default");
    
            RecalcDistance();
            CalculateProjMatrix();                  // 获取相机默认矩阵.
            ResetLookAroundPos();                   // 重置观察中心.
            LoadCursorTexture();                    // 加载鼠标图标.
        }
    
        /// <summary>
        /// 重置观察中心(观察中心在相机的前方).
        /// </summary>
        public void ResetLookAroundPos()
        {
            lookAroundPos = m_Camera.transform.position + m_Camera.transform.rotation * (Vector3.forward * distance);
        }
    
        /// <summary>
        /// 加载鼠标指针图标.
        /// </summary>
        private void LoadCursorTexture()
        {
            handCursorTexture = Resources.Load<Texture2D>("Textures/Hand");
            eyeCursorTexture = Resources.Load<Texture2D>("Textures/Eye");
            magnifierCursorTexture = Resources.Load<Texture2D>("Textures/Magnifier");
        }
    
        /// <summary>
        /// 设置鼠标样式.
        /// </summary>
        private void SetCursor(CursorType cursorType)
        {
            switch (cursorType)
            {
                case CursorType.DEFAULT:
                    Cursor.SetCursor(null, hotSpot, cursorMode);
                    break;
                case CursorType.HAND:
                    Cursor.SetCursor(handCursorTexture, hotSpot, cursorMode);
                    break;
                case CursorType.EYE:
                    Cursor.SetCursor(eyeCursorTexture, hotSpot, cursorMode);
                    break;
                case CursorType.MAGNIFIER:
                    Cursor.SetCursor(magnifierCursorTexture, hotSpot, cursorMode);
                    break;
                default:
                    Debug.LogError("未知指针类型.");
                    break;
            }
        }
    
        /// <summary>
        /// 更新输入.
        /// </summary>
        private void UpdateInput()
        {
            leftAltKeyDown = Input.GetKeyDown(KeyCode.LeftAlt);                            // 左Alt键-按下.
            rightAltKeyDown = Input.GetKeyDown(KeyCode.RightAlt);                          // 右Alt键-按下.
            leftAltKey = Input.GetKey(KeyCode.LeftAlt);                                    // 左Alt键-长按.
            rightAltKey = Input.GetKey(KeyCode.RightAlt);                                  // 右Alt键-长按.
            leftAltKeyUp = Input.GetKeyUp(KeyCode.LeftAlt);                                // 左Alt键-抬起.
            rightAltKeyUp = Input.GetKeyUp(KeyCode.RightAlt);                              // 右Alt键-抬起.
            rightMouseButtonDown = Input.GetMouseButtonDown((int)MouseButton.RIGHT);       // 鼠标右键-按下.
            leftMouseButtonDown = Input.GetMouseButtonDown((int)MouseButton.LEFT);         // 鼠标左键-按下.
            leftMouseButton = Input.GetMouseButton((int)MouseButton.LEFT);                 // 鼠标左键-长按.
            rightMouseButton = Input.GetMouseButton((int)MouseButton.RIGHT);               // 鼠标右键-长按.
            rightMouseButtonUp = Input.GetMouseButtonUp((int)MouseButton.RIGHT);           // 鼠标右键-抬起.
    
            middleMouseButton = Input.GetMouseButton((int)MouseButton.MIDDLE);             // 鼠标中键-按下.  
            middleMouseButtonUp = Input.GetMouseButtonUp((int)MouseButton.MIDDLE);         // 鼠标中键-抬起.
        }
    
        /// <summary>
        /// 计算距离.
        /// </summary>
        private void RecalcDistance()
        {
            Vector3 checkFarPos = m_Camera.transform.position + m_Camera.transform.rotation * (Vector3.forward * 1000);
            if (Physics.Linecast(m_Camera.transform.position, checkFarPos, out raycastHit))
            {
                // 如果相机中心有物体,则以物体到相机为距离
                distance = raycastHit.distance;
                if (selectedObj == null)
                {
                    selectedObj = raycastHit.collider.gameObject;
                }
            }
        }
    
        #endregion
    
        #region 切换视角
    
        /// <summary>
        /// 计算投影矩阵.
        /// </summary>
        private void CalculateProjMatrix()
        {
            currentProjMat = m_Camera.projectionMatrix;
    
            float aspect = m_Camera.aspect;
            float fov = m_Camera.fieldOfView;
            float size = m_Camera.orthographicSize;
            float far = m_Camera.farClipPlane;
            float near = m_Camera.nearClipPlane;
            float tan = Mathf.Tan(Mathf.Deg2Rad * fov * 0.5f);
    
            if (m_Camera.orthographic)
            {
                // 启动时相机是正交的
                viewType = ViewType._2D;
                fov = SetFovBySize(size);
            }
            else
            {
                // 启动时相机是透视的
                viewType = ViewType._3D;
                size = SetSizeByFov(fov);
            }
    
            // 透视投影矩阵.
            defaultPersProjMat = new Matrix4x4();
            //defaultPersProjMat = Matrix4x4.Perspective(fov, aspect, near, far);           // 透视矩阵也可直接调用这个来计算.
            defaultPersProjMat.SetRow(0, new Vector4(1.0f / (tan * aspect), 0, 0, 0));
            defaultPersProjMat.SetRow(1, new Vector4(0, 1.0f / tan, 0, 0));
            defaultPersProjMat.SetRow(2, new Vector4(0, 0, -(far + near) / (far - near), -2 * far * near / (far - near)));
            defaultPersProjMat.SetRow(3, new Vector4(0, 0, -1, 0));
    
            // 正交投影矩阵.
            defaultOrthProjMat = new Matrix4x4();
            defaultOrthProjMat.SetRow(0, new Vector4(1.0f / (aspect * size), 0, 0, 0));
            defaultOrthProjMat.SetRow(1, new Vector4(0, 1.0f / size, 0, 0));
            defaultOrthProjMat.SetRow(2, new Vector4(0, 0, -2f / (far - near), -(far + near) / (far - near)));
            defaultOrthProjMat.SetRow(3, new Vector4(0, 0, 0, 1));
        }
    
        /// <summary>
        /// 切换视角.
        /// </summary>
        private void SwitchViewType()
        {
            if (isChangingViewType)
            {
                viewTypeLerpTime += Time.deltaTime * 2.0f;
                if (viewType == ViewType._2D)
                {
                    // 切换到正交视图.
                    currentProjMat = Utils.Math.MatrixLerp(currentProjMat, defaultOrthProjMat, viewTypeLerpTime);
                }
                else
                {
                    // 切换到透视视图.
                    currentProjMat = Utils.Math.MatrixLerp(currentProjMat, defaultPersProjMat, viewTypeLerpTime);
                }
                m_Camera.projectionMatrix = currentProjMat;
                if (viewTypeLerpTime >= 1.0f)
                {
                    isChangingViewType = false;
                    viewTypeLerpTime = 0f;
    
                    if (viewType == ViewType._2D)
                    {
                        m_Camera.orthographic = true;
                    }
                    else
                    {
                        m_Camera.orthographic = false;
                    }
                    m_Camera.ResetProjectionMatrix();
                }
            }
        }
    
        /// <summary>
        /// 设置将要切换的视角.
        /// </summary>
        /// <param name="targetViewType">目标视角.</param>
        private void SetViewType(ViewType targetViewType)
        {
            if (viewType != targetViewType)
            {
                viewType = targetViewType;
                isChangingViewType = true;
                viewTypeLerpTime = 0f;
            }
        }
    
        /// <summary>
        /// 根据正交相机的size设置对应透视相机的fov
        /// </summary>
        /// <param name="size">正交相机高度的一半,即orthographicSize</param>
        private float SetFovBySize(float size)
        {
            float fov = 2.0f * Mathf.Atan(size / distance) * Mathf.Rad2Deg;
            m_Camera.fieldOfView = fov;
            return fov;
        }
    
        /// <summary>
        /// 根据透视相机的fov设置对应正交相机的即orthographicSize
        /// </summary>
        /// <param name="fov">透视相机的fov</param>
        private float SetSizeByFov(float fov)
        {
            float size = distance * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
            m_Camera.orthographicSize = size;
            return size;
        }
    
        #endregion
    
        #region 拉近拉远
    
        /// <summary>
        /// 拉近拉远.
        /// </summary>
        /// <remarks>鼠标滚轮滚动,向上滚动拉近相机,向下滚动拉远相机</remarks>
        private void Zoom()
        {
            float scrollWheelValue = Input.GetAxis(MOUSESCROLLWHEEL);
            if (!Utils.Math.IsEqual(scrollWheelValue, 0f))
            {
                // scrollWheelValue:滚轮向上为+ 向下为-
                // 同时滚轮向上,拉近相机;滚轮向下,拉远相机
                distance -= scrollWheelValue * zoomSpeed;
                distance = Mathf.Clamp(distance, minDistance, maxDistance);
    
                m_Camera.transform.position = lookAroundPos - m_Camera.transform.rotation * (Vector3.forward * distance);
    
                // 相机距离改变后需同时修改fov或orthographicSize以及投影矩阵,保证正交/透视视图切换效果
                CalculateProjMatrix();
            }
        }
    
        #endregion
    
        #region 拖动
    
        private bool isDraging = false;
        private Vector3 lastMousePos;
    
        /// <summary>
        /// 拖动.
        /// </summary>
        /// <remark>长按鼠标中键拖动</remark>
        private void Drag()
        {
            // 鼠标中键拖动相机.
            if (middleMouseButton)
            {
                if (isDraging == false)
                {
                    isDraging = true;
                    // 设置小手指针.
                    SetCursor(CursorType.HAND);
    
                    lastMousePos = Input.mousePosition;
                }
                else
                {
                    Vector3 newMousePos = Input.mousePosition;
                    Vector3 delta = newMousePos - lastMousePos;
                    m_Camera.transform.position += CalcDragLength(m_Camera, delta, distance);
                    lastMousePos = newMousePos;
    
                    // 相机移动,重新设置目标位置.
                    ResetLookAroundPos();
                }
            }
            if (middleMouseButtonUp)
            {
                isDraging = false;
                // 恢复默认指针.
                SetCursor(CursorType.DEFAULT);
            }
        }
    
        /// <summary>
        /// 计算拖拽距离.
        /// </summary>
        /// <param name="camera">相机</param>
        /// <param name="mouseDelta">鼠标移动距离</param>
        /// <param name="distance">相机距离观察物体的距离</param>
        private Vector3 CalcDragLength(Camera camera, Vector2 mouseDelta, float distance)
        {
            float rectHeight = -1;
            float rectWidth = -1;
            if (camera.orthographic)
            {
                rectHeight = 2 * camera.orthographicSize;
                //rectWidth = rectHeight / camera.aspect;
            }
            else
            {
                rectHeight = 2 * distance * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
            }
            rectWidth = Screen.width * rectHeight / Screen.height;
            Vector3 moveDir = -rectWidth / Screen.width * mouseDelta.x * camera.transform.right - rectHeight / Screen.height * mouseDelta.y * camera.transform.up;
    
            return moveDir;
        }
    
        #endregion
    
        #region 360°旋转观察
    
        /// <summary>
        /// 360°旋转查看.
        /// </summary>
        /// <remark>Alt+鼠标左键 或 鼠标右键</remark>
        private void LookAround()
        {
            if (leftAltKeyDown || rightAltKeyDown || rightMouseButtonDown)
            {
                SetCursor(CursorType.EYE);
    
                angle_X = m_Camera.transform.eulerAngles.y;
                angle_Y = m_Camera.transform.eulerAngles.x;
                angle_Z = m_Camera.transform.eulerAngles.z;
            }
    
            if ((leftAltKey && leftMouseButton)
                || (rightAltKey && leftMouseButton)
                || (!leftAltKey && !rightAltKey && rightMouseButton))
            {
                float deltaX = Input.GetAxis(MOUSEX);
                float deltaY = Input.GetAxis(MOUSEY);
    
                // 相机朝前和朝后,与鼠标的滑动方向相反
                if ((angle_Y > 90f && angle_Y < 270f) || (angle_Y < -90 && angle_Y > -270f))
                {
                    angle_X -= deltaX * rotateSensitivity;
                }
                else
                {
                    angle_X += deltaX * rotateSensitivity;
                }
                angle_Y -= deltaY * rotateSensitivity;
    
                angle_X = Utils.Math.ClampAngle(angle_X, -365, 365);   //限制旋转角度
                angle_Y = Utils.Math.ClampAngle(angle_Y, 0, 90);     
    
                SetCameraPos();
            }
    
            if (leftAltKeyUp || rightAltKeyUp || rightMouseButtonUp)
            {
                SetCursor(CursorType.DEFAULT);
            }
        }
    
        private void SetCameraPos()
        {
            Quaternion rotation = Quaternion.Euler(angle_Y, angle_X, angle_Z);
            Vector3 dir = Vector3.forward * - distance;
            m_Camera.transform.rotation = rotation;
            m_Camera.transform.position = lookAroundPos + rotation * dir;
        }
    
        #endregion
    
        #region 聚焦选中物体
    
        /// <summary>
        /// 聚焦选中物体.
        /// </summary>
        private void Focus()
        {
            if (leftMouseButtonDown)
            {
                Ray ray = m_Camera.ScreenPointToRay(Input.mousePosition);
    
                // Scene视图绘制射线方便测试.
                //Debug.DrawLine(ray.origin, ray.origin + ray.direction * raycastMaxDistance, Color.red, 3f);
    
                if (Physics.Raycast(ray, out raycastHit, raycastMaxDistance, raycastLayerMask))
                {
                    selectedObj = raycastHit.collider.gameObject;
                }
                else
                {
                    selectedObj = null;
                    ResetLookAroundPos();
                }
            }
    
            if (selectedObj != null)
            {
                if (Input.GetKeyDown(KeyCode.F))
                {
                    isFocusing = true;
                    focusTime = 0f;
                    cameraInitForward = m_Camera.transform.forward;
                    focusTargetForward = Vector3.Normalize(selectedObj.transform.position - m_Camera.transform.position);
    
                    focusInitPos = m_Camera.transform.position;
                    distance = focusDistance;
                    focusTargetPos = selectedObj.transform.position - focusTargetForward * distance;
                }
            }
    
            if (isFocusing)
            {
                focusTime += Time.deltaTime * focusSpeed;
                Vector3 forward = Vector3.Lerp(cameraInitForward, focusTargetForward, focusTime);
                m_Camera.transform.rotation = Quaternion.LookRotation(forward);
    
                m_Camera.transform.position = Vector3.Lerp(focusInitPos, focusTargetPos, focusTime);
    
                if (focusTime >= 1f)
                {
                    // 聚焦完毕.
                    focusTime = 0f;
                    isFocusing = false;
                    m_Camera.transform.rotation = Quaternion.LookRotation(focusTargetForward);
                    m_Camera.transform.position = focusTargetPos;
    
                    // 设置观察中心.
                    lookAroundPos = selectedObj.transform.position;
                }
            }
        }
    
        #endregion
    
        #region 各种视图
    
        /// <summary>
        /// 正视图.
        /// </summary>
        private void Front()
        {
            angle_X = 180;
            angle_Y = 0;
    
            SetCameraPos();
        }
    
        /// <summary>
        /// 后视图.
        /// </summary>
        private void Back()
        {
            angle_X = 0;
            angle_Y = 0;
    
            SetCameraPos();
        }
    
        /// <summary>
        /// 右视图.
        /// </summary>
        private void Right()
        {
            angle_X = -90;
            angle_Y = 0;
    
            SetCameraPos();
        }
    
        /// <summary>
        /// 左视图.
        /// </summary>
        private void Left()
        {
            angle_X = 90;
            angle_Y = 0;
    
            SetCameraPos();
        }
    
        /// <summary>
        /// 上视图(俯视图).
        /// </summary>
        private void Top()
        {
            angle_X = 0;
            angle_Y = 90;
    
            SetCameraPos();
        }
    
        /// <summary>
        /// 下视图.
        /// </summary>
        private void Down()
        {
            angle_X = 0;
            angle_Y = -90;
    
            SetCameraPos();
        }
    
        #endregion
    
        #region 放大/缩小
    
        /// <summary>
        /// 放大缩小.
        /// </summary>
        private void Magnifier()
        {
            if ((leftAltKey || rightAltKey) && rightMouseButton)
            {
                if (lastMousePosFov.Equals(Vector3.zero))
                {
                    lastMousePosFov = Input.mousePosition;
                    SetCursor(CursorType.MAGNIFIER);
                }
    
                float deltaX = lastMousePosFov.x - Input.mousePosition.x;
    
                if (viewType == ViewType._2D)
                {
                    // 透视视图改size
                    float size = m_Camera.orthographicSize + deltaX * 0.01f;
                    size = Mathf.Clamp(size, 1.0f, 8f);
                    m_Camera.orthographicSize = size;
    
                    // 调节size需同时修改相机透视模式下的fov
                    SetFovBySize(size);
                }
                else
                {
                    // 透视视图改fov
                    float fov = m_Camera.fieldOfView + deltaX * fovSensitivity;
                    fov = Mathf.Clamp(fov, minFov, maxFov);
                    m_Camera.fieldOfView = fov;
    
                    // 调节了fov需同时修改相机正交模式下的size
                    SetSizeByFov(fov);
                }
    
                lastMousePosFov = Input.mousePosition;
            }
    
            if (rightMouseButtonUp)
            {
                SetCursor(CursorType.DEFAULT);
                lastMousePosFov = Vector3.zero;
    
                // 重新计算投影矩阵.
                CalculateProjMatrix();
            }
        }
    
        #endregion
    
        #region wasd移动
    
        private void wasdMove()
        {
            Vector3 Face = transform.rotation * Vector3.forward;
            Face = Face.normalized;
    
            Vector3 Left = transform.rotation * Vector3.left;
            Left = Left.normalized;
    
            Vector3 Right = transform.rotation * Vector3.right;
            Right = Right.normalized;
    
            if (Input.GetKey("w"))
            {
                transform.position += Face * 5 * Time.deltaTime;
            }
    
            if (Input.GetKey("a"))
            {
                transform.position += Left * 5 * Time.deltaTime;
            }
    
            if (Input.GetKey("d"))
            {
                transform.position += Right * 5 * Time.deltaTime;
            }
    
            if (Input.GetKey("s"))
            {
                transform.position -= Face * 5 * Time.deltaTime;
            }
    
            if (Input.GetKey("q"))
            {
                transform.position -= Vector3.up * 5 * Time.deltaTime;
            }
    
            if (Input.GetKey("e"))
            {
                transform.position += Vector3.up * 5 * Time.deltaTime;
            }
            Camera.main.GetComponent<CameraController>().ResetLookAroundPos();
        }
        #endregion
    
        #region 右键旋转摄像机(位置不变)
        void RoCam()
        {
            if (Input.GetMouseButtonDown(1))
            {
                MouseDownPos = Input.mousePosition;
            }
    
            if (Input.GetMouseButton(1))
            {
                //Vector处理
                Vector3 Save = Input.mousePosition;
                Vector3 MovePos = Save - MouseDownPos;
                MovePos = MovePos.normalized;
                Vector3 _Rot = transform.rotation.eulerAngles;
                _Rot.x -= MovePos.y * 2;
                _Rot.y += MovePos.x * 2;
                _Rot.z += MovePos.z * 2;
                transform.eulerAngles = _Rot;
                Debug.Log(MovePos);
                MouseDownPos = Save;
    
                //Quaternion处理
                //Vector3 Save = Input.mousePosition;
                //Vector3 MovePos = Save - MouseDownPos;
                //MovePos = MovePos.normalized;
                //Vector3 _Rot = transform.rotation.eulerAngles;
                //_Rot.x -= MovePos.y * 2;
                //_Rot.y += MovePos.x * 2;
                //_Rot.z += MovePos.z * 2;
                //Quaternion MoveRot = Quaternion.Euler(_Rot);
                //transform.rotation = Quaternion.Slerp(transform.rotation, MoveRot, Time.deltaTime * 30);
                //MouseDownPos = Save;
            }
        }
    
        #endregion
    }
    

    移动端

    /***********************
     * 遇见你的眉眼,如清风明月。
     * Title:   "移动端控制摄像机"
     * Func:    1、平移摄像机
     *          2、推进、拉远摄像机(近大远小,效果:模型缩放)
     * -        3、旋转摄像机
     * UsedBy:      
     * Date:    2020
     * Author:  XC
     * Version: 1.0
     * Description: 
     ***********************/
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    public class CameraController_xc : MonoBehaviour
    {
        public Button Btn_ChangeRo;
        public bool isRotate ; //切换单指功能:平移或者旋转 
    
        public Button Btn_ResetPos; //复原归位
    
        //移动端
        private Touch oldTouch1;  //上次触摸点1(手指1)  
        private Touch oldTouch2;  //上次触摸点2(手指2)  
        
        public float MoveSpeed,RotateSpeed;  //移动端拖动速度、旋转速度
    
        //pc端
        public float ScrollWheelSpeed_pc; //鼠标滚轮速度
        public float MoveSpeed_pc, RotateSpeed_pc;
    
        private Vector3 MouseDownPos;
    
        void Start()
        {
            isRotate = true;
    
            MoveSpeed = 5f;
            RotateSpeed = 5f;
    
            ScrollWheelSpeed_pc = 10f;
            MoveSpeed_pc = 10f;
            RotateSpeed_pc = 10f;
        }
        private void OnEnable()
        {
            Btn_ChangeRo.onClick.AddListener(clickBtnRo);
            Btn_ResetPos.onClick.AddListener(clickBtn_Reset);
        }
        private void OnDisable()
        {
            Btn_ChangeRo.onClick.RemoveListener(clickBtnRo);
            Btn_ResetPos.onClick.RemoveListener(clickBtn_Reset);
        }
        void Update()
        {
    #if UNITY_ANDROID && !UNITY_EDITOR
            //没有触摸  
            if (Input.touchCount <= 0)
            {
                return;
            }
            //单点触摸
            if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved)
            {
                
                //得到手指移动的增量(只有X、Y值)
                Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;
                if (!isRotate)
                {
                    //相机移动
                    transform.Translate(-touchDeltaPosition.x * Time.deltaTime * MoveSpeed,
                        -touchDeltaPosition.y * Time.deltaTime * MoveSpeed, 0);
                }
                else
                {
                    //相机旋转
                    if (Mathf.Abs(touchDeltaPosition.y) > Mathf.Abs(touchDeltaPosition.x))
                    {
                        if (touchDeltaPosition.y > 0)
                        {
                            transform.Rotate(-touchDeltaPosition.y * Time.deltaTime * RotateSpeed, 0, 0);
                        }
                        else
                        {
                             transform.Rotate(-touchDeltaPosition.y * Time.deltaTime * RotateSpeed, 0, 0);
                        }
                    }
                    else
                    {
                        if (touchDeltaPosition.x > 0)
                        {
                            transform.Rotate(0, touchDeltaPosition.x * Time.deltaTime * RotateSpeed, 0, Space.World);
                        }
                        else
                        {
                            transform.Rotate(0, touchDeltaPosition.x * Time.deltaTime * RotateSpeed, 0, Space.World);
                        }
                    }
                }
            }
            else if (Input.touchCount >= 1)
            {
                //多点触摸, 放大缩小 
                Touch newTouch1 = Input.GetTouch(0);
                Touch newTouch2 = Input.GetTouch(1);
    
                //第2点刚开始接触屏幕, 只记录,不做处理  
                if (newTouch2.phase == TouchPhase.Began)
                {
                    oldTouch2 = newTouch2;
                    oldTouch1 = newTouch1;
                    return;
                }
    
                //计算老的两点距离和新的两点间距离,变大要放大模型,变小要缩放模型  
                float oldDistance = Vector2.Distance(oldTouch1.position, oldTouch2.position);
                float newDistance = Vector2.Distance(newTouch1.position, newTouch2.position);
    
                //两个距离之差,为正表示放大手势, 为负表示缩小手势  
                float offset = newDistance - oldDistance;
                float scaleFactor = offset / 100f;
    
                transform.position += transform.localRotation * (Vector3.forward * scaleFactor);
    
    
                //记住最新的触摸点,下次使用  
                oldTouch1 = newTouch1;
                oldTouch2 = newTouch2;
            }
    #elif UNITY_STANDALONE_WIN || UNITY_EDITOR
            //滚轮前进后退放大缩小
            float scrollWheelValue = Input.GetAxis("Mouse ScrollWheel");
            transform.position += transform.localRotation * (Vector3.forward * 
                scrollWheelValue * ScrollWheelSpeed_pc);
            //右键旋转
            if (Input.GetMouseButton(1))
            {
                if (Input.GetMouseButtonDown(1))
                {
                    MouseDownPos = Input.mousePosition;
                }
                if (Input.GetMouseButton(1))
                {
                    //Vector处理
                    Vector3 Save = Input.mousePosition;
                    Vector3 MovePos = Save - MouseDownPos;
                    MovePos = MovePos.normalized;
                    Vector3 _Rot = transform.rotation.eulerAngles;
                    _Rot.x -= MovePos.y * 2;
                    _Rot.y += MovePos.x * 2;
                    _Rot.z += MovePos.z * 2;
                    transform.eulerAngles = _Rot;
                    MouseDownPos = Save;
                }
            }
            // 鼠标中键拖动相机.
            if (Input.GetMouseButton(2))
            {
                float X = Input.GetAxis("Mouse X");
                float Y = Input.GetAxis("Mouse Y");
                //相机移动
                transform.Translate(-X * Time.deltaTime * MoveSpeed_pc,
                    -Y * Time.deltaTime * MoveSpeed_pc, 0);
            }
    #endif
    
            //限定位置
            Vector3 pos = transform.position;
            pos.x = Mathf.Clamp(pos.x, -20, 20);
            pos.y = Mathf.Clamp(pos.y, -9, 0);
            pos.z = Mathf.Clamp(pos.z, -45, 45);
            transform.position = pos;
    
        }
        void clickBtnRo()
        {
            if (isRotate)
            {
                isRotate = false;
            }
            else
            {
                isRotate = true;
            }
        }
        void clickBtn_Reset()
        {
            transform.position = new Vector3(-17.412f, 1.098661f, 41.43915f);
            transform.eulerAngles = new Vector3(27.433f, 142.668f, 0);
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Unity旋转和缩放02-控制摄像机

          本文链接:https://www.haomeiwen.com/subject/grbwuhtx.html