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

Unity中实现手机双指控制相机围绕物体轨道旋转的优化问题求助

双指操控相机轨道旋转的优化方案

问题根源

你的代码出现抖动、小幅手势引发大幅旋转的核心原因有4个:

  • 依赖射线检测得到的3D坐标计算旋转角度,一旦某一帧射线命中物体变化、或者没有命中返回Vector3.zero,计算出来的向量就会出现跳变,直接导致角度计算异常。
  • 没有做手势有效性校验,触摸采样本身的微小漂移、单指小幅移动都会被当成旋转输入触发计算。
  • 没有做旋转平滑,原始计算的角度直接赋值到相机,触摸的采样抖动会直接体现在相机运动上。
  • 旋转中心点如果走屏幕中心射线检测,也会因为命中结果不稳定导致旋转中心偏移,加重抖动。

优化方案

核心思路是放弃3D空间坐标计算,直接用屏幕二维坐标计算双指的角度变化,同时增加校验和平滑逻辑:

  1. 固定旋转中心:有选中物体时直接用选中物体位置,无选中物体可预设一个固定的轨道中心,不要每帧做屏幕中心射线检测。
  2. 用屏幕触摸点的二维向量计算角度变化,完全规避射线检测不稳定的问题。
  3. 增加手势阈值:双指移动的幅度小于3像素时不触发旋转,避免误触发。
  4. 增加平滑插值:计算得到的旋转角度不要直接应用,用插值过渡避免跳变。

优化后代码

// 可调参数,你可以根据实际体验调整
public float rotateSmoothTime = 0.1f;
public float minRotateThreshold = 3f; // 最小触发旋转的像素距离
public float rotateSpeed = 1f; // 旋转灵敏度

private float currentYVelocity;

public void Execute()
{
    if (_officeModel.Camera.orthographic || Input.touchCount != 2) return;
    _camera = _officeModel.Camera.transform;

    Touch t0 = Input.GetTouch(0);
    Touch t1 = Input.GetTouch(1);

    // 校验双指都处于移动状态
    if (t0.phase != TouchPhase.Moved || t1.phase != TouchPhase.Moved) return;

    // 计算上一帧和当前帧的双指屏幕向量
    Vector2 preVec = (t0.position - t0.deltaPosition) - (t1.position - t1.deltaPosition);
    Vector2 curVec = t0.position - t1.position;

    // 移动幅度小于阈值直接返回,避免小漂移触发旋转
    if (preVec.magnitude < minRotateThreshold || curVec.magnitude < minRotateThreshold) return;

    // 计算二维向量的角度变化,比3D计算稳定很多
    float angleDelta = Vector2.SignedAngle(preVec, curVec) * rotateSpeed;

    // 固定旋转中心,避免射线检测抖动
    Vector3 rotateCenter = _officeModel.SelectedObject != null ? 
        _officeModel.SelectedObject.transform.position : 
        new Vector3(0, 1, 0); // 无选中物体时可以替换成你的默认中心坐标

    // 平滑旋转,避免跳变
    float smoothAngle = Mathf.SmoothDamp(0, angleDelta, ref currentYVelocity, rotateSmoothTime);
    _camera.RotateAround(rotateCenter, Vector3.up, smoothAngle);

    _officeModel.CameraPos = _camera.position;
}

private Vector3 CreateRaycast(Vector3 direction)
{
    RaycastHit hit;
    Vector3 point = Vector3.zero;
    Ray ray = _officeModel.Camera.ScreenPointToRay(direction);
    if (Physics.Raycast(ray, out hit))
        point = hit.point;
    return point;
}

可调参数说明

  • rotateSmoothTime:值越大旋转越平滑,延迟也越高,建议范围0.05~0.2
  • minRotateThreshold:值越大越不容易误触发,建议范围2~5
  • rotateSpeed:控制旋转灵敏度,根据你的需求调整即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 06:36:03