Unity 移动鼠标旋转相机,相机围绕中心点旋转,角度限制

该代码实现了一个在Unity3D中控制相机围绕中心点旋转和缩放的功能。通过输入处理,限制了相机的旋转角度,并使用SmoothDampAngle进行平滑过渡。同时,当特定条件满足时,可以开启或关闭相机旋转。另外,还提供了缓动旋转和跟随中心点的更新方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using System;
using System.Linq;
using UnityEngine;
using UnityEngine.PlayerLoop;

public class CameraRotate : MonoBehaviour
{
    private CameraController cameraController;

    private class ZoomData
    {
        public float xAngle;
        public float yAngle;
        //public float distance;

        public ZoomData()
        {
        }

        public ZoomData(float xAngle, float yAngle)
        {
            //this.distance = distance;
            this.xAngle = xAngle;
            this.yAngle = yAngle;
        }
    }
    
    private void Start()
    {
        cameraController = UITools.GetOrCreateComponent<CameraController>(this.gameObject);
    }

    public void UpdateDo()
    {
        CheckOpenCameraRotate();
        RotateCamera();
        if (hadInitZoom)
        {
            UpdateZoom();
            UpdataCameraFollow();
        }
    }
    

    ZoomData curZoomData = new ZoomData();
    private float followDistance;
    private float xAngle;
    private float yAngle;
    private float tmp1;
    private float tmp2;
    public float zoomAngleSmoothing=0.5f;
    public float zoomParam = 2f;
    public float yAngleRightLimit = 30;
    public float yAngleLeftLimit=10;
    public float xAngleLimitUp=30;
    public float xAngleLimitDown=10;
    
    private void HandleInput(float offsetX,float offsetY)
    {
        
        curZoomData.xAngle += offsetY*zoomParam;
        if (curZoomData.xAngle > xAngleLimitUp)
        {
            curZoomData.xAngle = xAngleLimitUp;
        }
        else if (curZoomData.xAngle < xAngleLimitDown)
        {
            curZoomData.xAngle = xAngleLimitDown;
        }
        curZoomData.yAngle += offsetX*zoomParam;
        if (curZoomData.yAngle > yAngleLeftLimit)
        {
            curZoomData.yAngle = yAngleLeftLimit;
        }
        else if (curZoomData.yAngle < yAngleRightLimit)
        {
            curZoomData.yAngle = yAngleRightLimit;
        }
        Debug.Log("HandleInput:"+curZoomData.yAngle);

    }

    private bool hadInitZoom = false;
    private void InitZoom()
    {
        this.followDistance = Vector3.Distance(this.transform.position, sceneCenterPoint);
        
        this.xAngle = this.transform.eulerAngles.x;
        this.yAngle = this.transform.eulerAngles.y;
        this.curZoomData.xAngle = this.xAngle;
        this.curZoomData.yAngle = this.yAngle;
        yAngleRightLimit = this.curZoomData.yAngle - yAngleRightLimit;
        yAngleLeftLimit = this.curZoomData.yAngle + yAngleLeftLimit;
        xAngleLimitDown = this.curZoomData.xAngle - xAngleLimitDown;
        xAngleLimitUp = this.curZoomData.xAngle + xAngleLimitUp;

        hadInitZoom = true;
    }
    private void UpdateZoom()
    {
        ZoomData data = this.curZoomData;
        if (Mathf.Abs(data.yAngle - this.yAngle) > 0.01f||Mathf.Abs(data.xAngle - this.xAngle) > 0.01f)
        {
            this.xAngle = Mathf.SmoothDampAngle(this.xAngle, data.xAngle, ref tmp1, zoomAngleSmoothing);
            this.yAngle = Mathf.SmoothDampAngle(this.yAngle, data.yAngle, ref tmp2, zoomAngleSmoothing);
            Debug.Log("UpdateZoom:"+yAngle);
        }
        
    }
    private void UpdataCameraFollow()
    {
        Quaternion quaternion = Quaternion.Euler(this.xAngle, this.yAngle, 0);
        Vector3 dPos = sceneCenterPoint + (quaternion * Vector3.back).normalized * followDistance;
        this.transform.rotation = quaternion;//固定旋转,否则由于缓动,摄像机旋转会变化
        this.transform.position = dPos;
        //Debug.Log("UpdataCameraFollow:"+this.transform.rotation);
    }
    
//------------------------检测是否开启相机旋转---------------------------------    
    public string cameraFightAnimName
    {
        get
        {
            return "Fight";
        }
    }
    private int cameraFightAnimHash;
    private Animator cameraAnimator;

    private bool checkCameraRotate;

    public void SetCheckCameraRotate(bool check)
    {
        checkCameraRotate = check;
        if (checkCameraRotate)
        {
            GameObject sceneRoot = GameObject.Find("SceneRoot");
            if (sceneRoot != null)
            {
                cameraAnimator = sceneRoot.transform.GetComponent<Animator>();
                cameraFightAnimHash = Animator.StringToHash(this.cameraFightAnimName);
            }
        }
        else
        {
            cameraAnimator = null;
        }
    }
    void CheckOpenCameraRotate()
    {
        if (!checkCameraRotate) return;
        if (cameraAnimator!=null && this.cameraAnimator.GetCurrentAnimatorStateInfo(0).shortNameHash==cameraFightAnimHash)
        {
            checkCameraRotate = false;
            
            originCameraPos = this.transform.position;
            originCameraAngles.x = this.transform.eulerAngles.x;
            originCameraAngles.y = this.transform.eulerAngles.y;
            lastCameraPos = this.transform.position;
            lastCameraAngles = this.transform.eulerAngles;
            OpenRotateCamera(true);
        }
    } 
//-----------------------------------------------------

//------用户滑动屏幕,相机围绕中心点旋转----------

    public Transform centerTrs;
    private bool canRotateCamera;
    [SerializeField]
    private float rotateSpeed;//旋转速度
    [SerializeField]
    private float limitAnglesX;//上下旋转角度限制
    [SerializeField]
    private float limitAnglesYLeft;//左旋转角度限制
    [SerializeField]
    private float limitAnglesYRight;//右旋转角度限制
    public Vector3 sceneCenterPoint;
    private float maxEulerAnglesX;
    private float minEulerAnglesX;
    private float maxEulerAnglesY;
    private float minEulerAnglesY;
    
    private Vector3 originCameraPos;
    private Vector3 originCameraAngles;
    public Vector3 lastCameraPos;
    public Vector3 lastCameraAngles;

    private bool hadInitCfg;
    void InitCfg()
    {
        if (hadInitCfg) return;
        hadInitCfg = true;
        int rotateSpeedId = 1000101;
        int rotateAngleXId = 1000102;
        int limitAnglesYLeftId = 1000103;
        int limitAnglesYRightId = 1000104;
        ConfigData.ClientParams info = ConfigManager.GetConfigData_ItemById<ConfigData.ClientParams>(rotateSpeedId);
        if (info==null || !float.TryParse(info.value, out rotateSpeed))
        {
            rotateSpeed = 1;
        }
        info = ConfigManager.GetConfigData_ItemById<ConfigData.ClientParams>(rotateAngleXId);
        if (info==null || !float.TryParse(info.value, out limitAnglesX))
        {
            limitAnglesX = 15;
        }
        info = ConfigManager.GetConfigData_ItemById<ConfigData.ClientParams>(limitAnglesYLeftId);
        if (info==null || !float.TryParse(info.value, out limitAnglesYLeft))
        {
            limitAnglesYLeft = 15;
        }
        info = ConfigManager.GetConfigData_ItemById<ConfigData.ClientParams>(limitAnglesYRightId);
        if (info==null || !float.TryParse(info.value, out limitAnglesYRight))
        {
            limitAnglesYRight = 15;
        }
            
    }
    void InitRecordCamera()
    {
        InitCfg();
    }    
    public void OpenRotateCamera(bool open)
    {
        InitRecordCamera();
        cameraController.IsUpdateCameraInBindTrans = !open;
        CanRotateCamera(open);
        AngleLimit();
        
        GameObject go = GameObject.Find("Cam_Pos");
        if (go != null)
        {
            sceneCenterPoint = go.transform.position;
        }
        else
        {
            sceneCenterPoint = new Vector3(8.93f,0,5.11f);
        }

        InitZoom();
        
    }

    public void CanRotateCamera(bool can)
    {
        canRotateCamera = can;
    }

    private Vector3 oldMousePos;
    private Vector3 newMousePos;
    private bool isPressFirst=false;
    [SerializeField]
    private float pressParams=0.02f;
    void RotateCamera()
    {
        if (!canRotateCamera || cameraController.IsUpdateCameraInBindTrans)
        {
            return;
        }
        if (Input.GetMouseButton(0))
        {
            if (!isPressFirst)
            {
                oldMousePos = Input.mousePosition;
                isPressFirst = true;
                return;
            }
            else
            {
                newMousePos = Input.mousePosition;
                isPressFirst = false;
            }
            float mouseX = 0;
            float mouseY = 0;
            mouseX = newMousePos.x - oldMousePos.x;
            mouseY = newMousePos.y - oldMousePos.y;
            mouseX *= pressParams;
            mouseY *= pressParams;
            if (Mathf.Abs(mouseX) > 0.01f || Mathf.Abs(mouseY) > 0.01f)
            {
               Debug.Log("测试:mouseX:"+mouseX+",mouseY:"+mouseY+",XX:"+Input.GetAxis("Mouse X")+",YY:"+Input.GetAxis("Mouse Y"));
                //HandleInput( Input.GetAxis("Mouse X"),  Input.GetAxis("Mouse Y"));
                HandleInput(mouseX, mouseY);
                //RotateAround(mouseX,mouseY);    
            }
        }
        else
        {
            if(isPressFirst)
                isPressFirst = false;
        }
    }
    void RotateAround(float mouseX,float mouseY)
    {
        // float mouseX = Input.GetAxis("Mouse X");
        // float mouseY = Input.GetAxis("Mouse Y");
        
        Vector3 rotateDir = Vector3.up;
        float rotateValue = 0;
        //左右旋转
        float rotateAngleY = mouseX * rotateSpeed;
        rotateValue = rotateAngleY;
        transform.RotateAround(sceneCenterPoint, rotateDir, rotateValue);
        float hadRotateAngleY = transform.eulerAngles.y + rotateAngleY;
        if (rotateAngleY>0 && 
            hadRotateAngleY<180 && 
            hadRotateAngleY > maxEulerAnglesY)
        {
            rotateValue = rotateAngleY-(hadRotateAngleY-maxEulerAnglesY);
        }
        else if(rotateAngleY<0 && 
                hadRotateAngleY>180 && 
                hadRotateAngleY< minEulerAnglesY)
        {
            rotateValue = rotateAngleY+(minEulerAnglesY-hadRotateAngleY);
        }
        transform.RotateAround(sceneCenterPoint, rotateDir, rotateValue);

        //垂直旋转
        rotateDir = transform.right;
        float rotateAngleX = -mouseY * rotateSpeed;
        rotateValue = rotateAngleX;
        transform.RotateAround(sceneCenterPoint, rotateDir, rotateValue);
        float hadRotateAngleX = transform.eulerAngles.x + rotateAngleX;
        if (rotateAngleX > 0 &&
            maxEulerAnglesX <= 90 &&
            hadRotateAngleX < 180 &&
            hadRotateAngleX >= maxEulerAnglesX)
        {
            rotateValue = rotateAngleX-(hadRotateAngleX - maxEulerAnglesX);
        }
        else if (rotateAngleX > 0 &&
                 maxEulerAnglesX <= 90 &&
                 transform.eulerAngles.z>=179 &&
                 hadRotateAngleX <= maxEulerAnglesX)
        {
            rotateValue = rotateAngleX-(maxEulerAnglesX - hadRotateAngleX);
        }
        else if (rotateAngleX > 0 &&
                 maxEulerAnglesX > 90 &&
                 transform.eulerAngles.z>=179 &&
                 hadRotateAngleX < 180-maxEulerAnglesX)
        {
            rotateValue = rotateAngleX-( (180-maxEulerAnglesX)-hadRotateAngleX);
        }
        
        else if (rotateAngleX < 0 &&
                 hadRotateAngleX < 180 && 
                 minEulerAnglesX < 180 &&
                 hadRotateAngleX < minEulerAnglesX)
        {
            rotateValue = rotateAngleX+(minEulerAnglesX-hadRotateAngleX);
        } 
        else if (rotateAngleX < 0 &&
                 hadRotateAngleX>180 &&
                 hadRotateAngleX <360- minEulerAnglesX)
        {
            rotateValue = rotateAngleX+((360-minEulerAnglesX)-hadRotateAngleX);
        }
        else if (rotateAngleX < 0 &&
                 hadRotateAngleX > 180 &&
                 hadRotateAngleX < minEulerAnglesX)
        {
            rotateValue = rotateAngleX-(hadRotateAngleX-minEulerAnglesX);
        }
        transform.RotateAround(sceneCenterPoint, rotateDir, rotateValue);
        
        lastCameraPos = this.transform.position;
        lastCameraAngles = this.transform.eulerAngles;

    }
    void AngleLimit()
    {
        maxEulerAnglesY = originCameraAngles.y + limitAnglesYLeft;
        if (maxEulerAnglesY >= 360)
        {
            maxEulerAnglesY = maxEulerAnglesY- 360;
        }
        else if (maxEulerAnglesY<0)
        {
            maxEulerAnglesY = 360 + maxEulerAnglesY;
        }
        minEulerAnglesY = originCameraAngles.y - limitAnglesYRight;
        if (minEulerAnglesY >= 360)
        {
            minEulerAnglesY = minEulerAnglesY- 360;
        }
        else if (minEulerAnglesY<0)
        {
            minEulerAnglesY = 360 + minEulerAnglesY;
        }
        
        maxEulerAnglesX = originCameraAngles.x+ limitAnglesX;
        if (maxEulerAnglesX >= 360)
        {
            maxEulerAnglesX = maxEulerAnglesX- 360;
        }
        else if (maxEulerAnglesX<0)
        {
            maxEulerAnglesX = 360 + maxEulerAnglesX;
        }
        minEulerAnglesX = originCameraAngles.x - limitAnglesX;
        if (minEulerAnglesX >= 360)
        {
            minEulerAnglesX = minEulerAnglesX- 360;
        }
        else if (minEulerAnglesX<0)
        {
            minEulerAnglesX = 360 + minEulerAnglesX;
        }
    }
//----------------------------------------------------------------------------------------
    
    
    
    TweenRotation tr;
    public void TweenRotation(Vector3 to,float duration,float delay=0)
    {
        tr = UITools.GetOrCreateComponent<TweenRotation>(this.gameObject);
        //tr.delay = delay;
        tr.method = UITweener.Method.Linear;
        tr.@from = transform.eulerAngles;
        tr.to = to;
        tr.duration = duration;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值