鼠标控制摄像机旋转,平移,物体的移动

本文介绍了一个Unity脚本,该脚本实现了通过鼠标点击并拖动物体移动、围绕指定物体旋转相机以及通过鼠标平移调整相机视野的功能。文章详细解释了如何使用射线检测、平滑旋转和平移等技术。

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

 #region 点击物体移动
    public Camera ca;
    public GameObject DianjiObj;//点击到的物体
    Ray ray;//射线
    RaycastHit raycast;//射线返回的碰撞信息
    Vector3 StarMousePos;//一开始鼠标的位置
    Vector3 vector3;//要移动的距离
    Vector3 EndV3;
    #endregion
    #region 绕着物体旋转
    public Transform target;//声明一个观察目标  绕着这个物体旋转
    //旋转角度
    private float mx = 0.0f;
    private float my = 0.0f;
    //角度限制
    private float MinLimitY = -180;
    private float MaxLimitY = 180;
    //旋转速度
    public float SpeedX = 240;
    public float SpeedY = 120;
    //储存角度
    private Quaternion mRotation;
    //是否使用平滑差值  
    public bool isNeedDamping = true;
    //速度  
    public float DampingSpeed = 10F;
    //摄像机到物体的观察距离
    private float distance = 8f;
    //缩放视野
    public float minDistance = 2;
    public float maxDistance = 30;
    public float mSpeed = 10;
    #endregion
    #region 鼠标拖动平移相机视野
    public float MoveSpeed = 0.1f;
    #endregion
    //鼠标枚举
    private enum MouseButton
    {
        MouseButton_Lift=0,
        MouseButton_Right=1,
        MouseButton_Midle=2
    }
 void Start ()
    {
        //获取鼠标一开始的位置
        StarMousePos = Input.mousePosition;
        mx = transform.eulerAngles.x;
        my = transform.eulerAngles.y;
    }
 void Update ()
    {
        m_Move();
        m_Rotate();
        m_PingYI();
    }
    private void m_Move()//点击物体移动
    {
        if (Input.GetMouseButtonDown((int)MouseButton.MouseButton_Lift))
        {
            //把鼠标的世界坐标转化射线的屏幕发射位置
            ray = ca.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray,out raycast))
            {
                DianjiObj = GameObject.Find(raycast.transform.name);
            }
        }
        if (Input.GetMouseButton((int)MouseButton.MouseButton_Lift))
        {
            if (DianjiObj)
            {
                //获得物体的屏幕坐标
                Vector3 ObjPingMu = Camera.main.WorldToScreenPoint(DianjiObj.transform.position);
                //保存屏幕位置
                Vector3 ObjMouse = new Vector3(Input.mousePosition.x,Input.mousePosition.y, ObjPingMu.z);
                vector3 = Camera.main.ScreenToWorldPoint(ObjMouse) - DianjiObj.transform.position;
                EndV3 = vector3 + DianjiObj.transform.position;
                DianjiObj.transform.position = EndV3;
            }
        }
    }
    private void m_Rotate()//绕着物体旋转
    {
        if (target != null && Input.GetMouseButton((int)MouseButton.MouseButton_Right))
        {
            mx += Input.GetAxis("Mouse X") * SpeedX * 0.02f;
            my -= Input.GetAxis("Mouse Y") * SpeedY * 0.02f;
            my = ClampAngle(my, MinLimitY, MaxLimitY);
           
            
            Quaternion rotateAngle = Quaternion.Euler(my, mx, 0);//摄像机偏转角度 
            Vector3 disVector = new Vector3(0.0f, 0.0f, -distance);
            Vector3 position = rotateAngle * disVector + target.position;
            ////开始计算旋转
            mRotation = Quaternion.Euler(my, mx, 0);
            if (isNeedDamping)
            {
                transform.rotation = Quaternion.Lerp(transform.rotation, mRotation, Time.deltaTime * DampingSpeed);
                transform.position = Vector3.Lerp(transform.position, position, Time.deltaTime * DampingSpeed);
            }
            else
            {
                transform.rotation = mRotation;
                transform.position = position;
            }
        }
    }
    private void m_PingYI()
    {
        if(Input.GetAxis("Horizontal") != 0)
        {
            transform.Translate(Input.GetAxis("Horizontal") * MoveSpeed, 0, 0);
        }
        if (Input.GetAxis("Vertical") != 0)
        {
            transform.Translate(0, Input.GetAxis("Vertical") * MoveSpeed, 0);
        }
    }
    private float ClampAngle(float angle, float min, float max)
    {
        if (angle < -360)
        {
            angle += 360;
        }
        if (angle > 360)
        {
            angle -= 360;
        }
        return Mathf.Clamp(angle,min,max);
    }
<think>好的,我现在需要帮助用户在Unity中实现通过鼠标控制摄像机移动旋转和缩放功能。首先,我应该回忆一下Unity中常用的输入处理方法和摄像机控制的基本组件。用户提到了滚轮缩放、中键平移以及右键旋转,这些都是常见的操作方式。 首先,关于缩放,通常是通过鼠标滚轮来调整摄像机与目标点的距离。需要用到Input.GetAxis("Mouse ScrollWheel")来获取滚轮的输入,然后调整摄像机的距离,可能还需要限制最小和最大距离,防止穿模或者过远。这部分可以参考引用[1]中的Distance变量控制方法。 接下来是平移,也就是用鼠标中键拖动来移动摄像机的位置。需要检测鼠标中键是否被按下,然后根据鼠标在屏幕上的移动来调整摄像机的位置。这里可能需要将屏幕坐标转换为世界坐标的位移,或者根据摄像机的朝向移动。引用[2]中提到了双手指滑动移动摄像机,但这里用户用的是鼠标中键,可能需要类似的逻辑,用Input.GetMouseButton(2)来检测中键按下,然后通过Input.GetAxis("Mouse X")和"Mouse Y"来获取移动量,乘以速度和时间,再应用平移。 然后是旋转,通常用鼠标右键来控制摄像机旋转,比如绕目标点旋转。需要处理鼠标右键按下时的输入,根据鼠标移动来调整摄像机旋转角度。可能需要使用Transform.Rotate方法,同时限制垂直角度避免翻转,如引用[3]中的Rotate方法和角度限制。这里要注意绕Y轴的水平旋转和绕X轴的垂直旋转,同时要确保旋转是基于世界坐标系还是局部坐标系,可能需要使用Space.World参数。 然后需要将这些功能整合到一个脚本中,挂载到摄像机上。可能需要定义几个变量,比如移动速度、旋转速度、缩放速度,以及距离的限制。在Update函数中处理不同输入条件下的逻辑,可能需要使用条件语句来检测鼠标按键的状态,并根据不同的按键执行不同的操作。 另外,需要注意摄像机的父物体是否有一个目标点,或者摄像机自身的位置和旋转如何影响这些操作。例如,旋转时可能需要绕某个目标点旋转,而平移则是相对于摄像机的当前朝向移动。 还有可能遇到的问题包括:坐标系转换、欧拉角旋转的万向锁问题、移动时的平滑插值等。是否需要使用插值来让移动旋转更平滑?可能需要根据用户的需求来决定是否加入Lerp或SmoothDamp函数。 测试过程中,可能需要检查各个输入是否被正确检测,移动方向是否符合预期,旋转是否不会出现翻转,缩放是否在设定范围内。例如,当鼠标中键按下时,左右移动鼠标应该让摄像机平移动,而上下移动则是垂直或前后移动,这取决于摄像机当前的朝向。 最后,可能需要提供一个示例脚本,整合上述所有功能,并注释清楚各个参数的作用,方便用户调整。同时,引用相关的参考资料,如提到的引用[1]、[2]、[3]中的方法,确保代码的正确性。</think>在Unity中实现鼠标控制摄像机移动旋转和缩放,可通过以下代码实现功能整合: ```csharp using UnityEngine; public class CameraController : MonoBehaviour { public float moveSpeed = 5f; // 移动速度 public float rotateSpeed = 2f; // 旋转速度 public float zoomSpeed = 10f; // 缩放速度 public float minDistance = 2f; // 最近距离 public float maxDistance = 15f; // 最远距离 public Transform target; // 观察目标 private Vector3 offset; // 初始偏移量 private float currentDistance; // 当前距离 private Vector2 lastMousePos; // 记录鼠标位置 void Start() { offset = transform.position - target.position; currentDistance = offset.magnitude; } void Update() { // 缩放控制 HandleZoom(); // 中键平移 if (Input.GetMouseButton(2)) { HandlePan(); } // 右键旋转 if (Input.GetMouseButton(1)) { HandleRotation(); } } void HandleZoom() { float scroll = Input.GetAxis("Mouse ScrollWheel"); currentDistance -= scroll * zoomSpeed; currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance); transform.position = target.position + transform.forward * -currentDistance; } void HandlePan() { float x = Input.GetAxis("Mouse X") * moveSpeed; float y = Input.GetAxis("Mouse Y") * moveSpeed; Vector3 move = new Vector3(-x, -y, 0) * Time.deltaTime; transform.Translate(move, Space.Self); target.Translate(move, Space.Self); } void HandleRotation() { float x = Input.GetAxis("Mouse X") * rotateSpeed; float y = -Input.GetAxis("Mouse Y") * rotateSpeed; // 水平旋转 transform.RotateAround(target.position, Vector3.up, x); // 垂直旋转(带角度限制) Vector3 verticalAxis = transform.TransformDirection(Vector3.right); transform.RotateAround(target.position, verticalAxis, y); // 限制垂直角度(-30°到80°) Vector3 angles = transform.eulerAngles; angles.z = 0; if(angles.x > 180) angles.x -= 360; angles.x = Mathf.Clamp(angles.x, -30f, 80f); transform.eulerAngles = angles; // 保持观察目标 transform.position = target.position + transform.forward * -currentDistance; } } ``` ### 实现说明: 1. **缩放控制**:通过鼠标滚轮调整$Distance$变量,使用$Mathf.Clamp$限制缩放范围[^1] 2. **平移控制**:中键拖动时根据鼠标移动量计算位移,使用$Space.Self$坐标系保持方向一致性[^2] 3. **旋转控制**: - 水平旋转使用$RotateAround$绕Y轴旋转 - 垂直旋转通过转换坐标系限制角度范围,避免摄像机翻转[^3] 4. **目标跟踪**:始终以target为中心点进行旋转和缩放 ### 参数配置建议: 1. 将脚本挂载到主摄像机 2. 在Inspector面板指定target对象(可以是空物体) 3. 根据项目需求调整速度参数: - 移动速度建议5-10 - 旋转速度建议1-3 - 缩放速度建议10-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alxes_七局

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值