美文网首页
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