You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity相机环绕脚本问题:首次点击屏幕时相机异动修复需求

问题分析与修复方案

问题根源

  1. 变量复用混淆:原脚本中currentPosition既存储相机初始位置,又被用来存储鼠标位置,导致首次点击时逻辑计算异常。
  2. 半径计算错误:radius = currentPosition.magnitude计算的是相机到世界原点的距离,而非到目标物体target的实际距离,引发平移时的位置偏移。
  3. 变量拼写错误:拖拽逻辑中使用了未定义的rotXaxis和rotYaxis,实际应为rotationXAxis和rotationYAxis,会导致意外的旋转值。
  4. 初始鼠标位置未正确初始化:首次点击前currentPosition存储的是相机位置,若未及时切换为鼠标位置,会造成首次拖拽时的错误计算。

修复后的完整代码

public class CameraOrbit : MonoBehaviour
{
    public Camera cam;
    public Transform target;
    public float radius = 10;
    // 单独存储鼠标位置,避免与相机位置混淆
    private Vector3 _lastMousePos;

    public Vector3 positionPreOffset;
    public Vector3 rotationPreOffset;

    private void Start()
    {
        // 计算初始相机位置
        Vector3 desiredPosition = target.position + target.rotation * positionPreOffset;
        cam.transform.position = desiredPosition;

        // 计算初始相机旋转
        Quaternion desiredRotation = target.rotation * Quaternion.Euler(rotationPreOffset);
        cam.transform.rotation = desiredRotation;

        // 正确计算相机到目标的距离(而非到原点)
        radius = Vector3.Distance(cam.transform.position, target.position);
    }

    private void LateUpdate()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 按下鼠标时记录当前鼠标视口位置
            _lastMousePos = cam.ScreenToViewportPoint(Input.mousePosition);
        }
        else if (Input.GetMouseButton(0))
        {
            // 获取当前鼠标视口位置
            Vector3 currentMousePos = cam.ScreenToViewportPoint(Input.mousePosition);
            // 计算鼠标移动差值
            Vector3 mouseDelta = _lastMousePos - currentMousePos;

            // 根据鼠标移动计算旋转角度
            float yaw = -mouseDelta.x * 90f;
            float pitch = mouseDelta.y * 90f;

            // 获取相机当前相对于目标的旋转
            Quaternion currentRotation = cam.transform.rotation;
            // 应用新的旋转(绕Y轴旋转是全局Y,绕X轴是相机自身X)
            Quaternion newRotation = currentRotation * Quaternion.Euler(pitch, yaw, 0f);
            cam.transform.rotation = newRotation;

            // 根据新旋转重新计算相机位置,保持与目标的距离
            cam.transform.position = target.position + newRotation * new Vector3(0f, 0f, -radius);

            // 更新上一帧鼠标位置
            _lastMousePos = currentMousePos;
        }
    }
}

关键修改点

  • 分离变量:新增_lastMousePos专门存储鼠标位置,避免与相机位置变量混淆。
  • 修正半径计算:用Vector3.Distance计算相机到target的实际距离,确保平移时保持正确的环绕半径。
  • 修复拼写错误:将未定义的旋转变量名替换为更直观的pitch(X轴旋转)和yaw(Y轴旋转)。
  • 优化旋转逻辑:基于相机当前旋转进行增量调整,而非每次重置到target位置再旋转,让视角调整更平滑,彻底解决首次点击的异动问题。
  • 确保初始鼠标位置正确:仅在鼠标按下时记录鼠标位置,避免首次拖拽时使用错误的初始值。

内容的提问来源于stack exchange,提问作者RSRY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 00:22:43