实现类似《过山车之星》的GameObject旋转系统:解决光标与物体跳转问题
嘿,这个问题我做模拟经营类游戏的物体编辑系统时正好踩过坑!你现在的核心问题是把「旋转的鼠标输入」和「物体位置跟随鼠标」给绑在一起了——得把这俩彻底拆开,同时用光标锁定来避免额外干扰,就能解决跳转问题了。
方案1:用鼠标相对位移驱动旋转(最贴合《过山车之星》逻辑)
这种方式完全不碰物体的位置,只利用鼠标的移动增量来控制旋转,从根源上杜绝位置跳转的问题。适合自由旋转场景,代码示例(Unity环境):
public GameObject targetObject; public float rotationSpeed = 6f; public KeyCode rotateTriggerKey = KeyCode.LeftAlt; // 自定义旋转触发键 private bool isRotating = false; void Update() { // 开启旋转模式 if (Input.GetKeyDown(rotateTriggerKey)) { isRotating = true; // 锁定光标到屏幕中心并隐藏,避免光标乱跑干扰操作 Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; } // 关闭旋转模式 else if (Input.GetKeyUp(rotateTriggerKey)) { isRotating = false; // 恢复光标正常状态 Cursor.lockState = CursorLockMode.None; Cursor.visible = true; } if (isRotating) { // 获取鼠标的相对移动量(这是旋转的核心输入) float mouseXDelta = Input.GetAxis("Mouse X") * rotationSpeed; float mouseYDelta = Input.GetAxis("Mouse Y") * rotationSpeed; // 围绕物体自身的Y轴(水平旋转)和X轴(垂直旋转)转动 // 要是需要围绕世界轴旋转,把Space.Self改成Space.World即可 targetObject.transform.Rotate(Vector3.up, mouseXDelta, Space.Self); targetObject.transform.Rotate(Vector3.right, -mouseYDelta, Space.Self); } }
这个逻辑和《过山车之星》完全一致:按住触发键后,鼠标的拖动方向直接对应旋转方向,全程不改变物体位置,释放按键后自然不会有跳转。
方案2:如果需要围绕鼠标指向的平面旋转
要是你的需求是让物体围绕鼠标点击的平面法线旋转(比如在地面上旋转物体),那要在旋转开始时记录初始状态,之后只计算鼠标的偏移量来旋转,绝对不能直接把物体移到鼠标位置:
public GameObject targetObject; public float rotationSpeed = 3f; public KeyCode rotateTriggerKey = KeyCode.LeftAlt; public LayerMask targetPlaneLayer; // 选择你要检测的平面图层 private bool isRotating = false; private Vector3 initialMouseHitPos; private Quaternion initialObjectRotation; void Update() { if (Input.GetKeyDown(rotateTriggerKey)) { isRotating = true; Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; // 记录旋转启动时的鼠标射线交点和物体初始旋转角度 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, targetPlaneLayer)) { initialMouseHitPos = hit.point; initialObjectRotation = targetObject.transform.rotation; } } else if (Input.GetKeyUp(rotateTriggerKey)) { isRotating = false; Cursor.lockState = CursorLockMode.None; Cursor.visible = true; } if (isRotating) { Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, targetPlaneLayer)) { // 计算鼠标从初始点到当前点的水平偏移 Vector3 offset = hit.point - initialMouseHitPos; float rotateAngle = offset.x * rotationSpeed; // 基于初始旋转叠加角度,完全不修改物体位置 targetObject.transform.rotation = initialObjectRotation * Quaternion.Euler(0, rotateAngle, 0); } } }
这里的核心是:旋转只依赖鼠标的相对偏移量,全程不修改物体的position属性,所以释放按键后不会出现跳位置的情况。
关于阻止光标移动
上面的代码里已经用到了Unity的光标锁定API:
- 按住旋转键时,设置
Cursor.lockState = CursorLockMode.Locked,光标会被固定在屏幕中心且不可见,此时鼠标移动只会产生相对位移,不会让光标乱跑。 - 释放按键后恢复
Cursor.lockState = CursorLockMode.None,光标就回到正常状态了。
这种方式既解决了位置跳转问题,又让操作体验和《过山车之星》保持一致。
内容的提问来源于stack exchange,提问作者Steve




