Unity安卓平台相机捏合缩放/变换异常问题求助
问题根源
你的捏合缩放逻辑依赖历史帧的距离差累加,且未在捏合结束时重置历史数据。松开捏合后,_pinchDistances数组仍保留上一次捏合的旧数据,新的小幅度捏合触发时,旧数据的平均差会导致_distance被错误跳变到最大值。
修复方案
改用比例缩放逻辑:每次捏合开始时记录当前手指间距和相机距离,后续通过当前间距与初始间距的比例计算相机距离;同时在捏合结束时重置状态,确保每次捏合都从当前相机状态开始。
修改后的完整代码
// 新增变量记录捏合初始状态 private float _initialPinchDistance; private float _initialCameraDistance; private bool _isPinching = false; void LateUpdate() { if (_target) { if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved) { // 单指旋转逻辑保留 _velocityX += _xSpeed * Input.GetTouch(0).deltaPosition.x * 0.02f; _velocityY += _ySpeed * Input.GetTouch(0).deltaPosition.y * 0.02f; } else if (Input.touchCount == 2) { Touch touchZero = Input.GetTouch(0); Touch touchOne = Input.GetTouch(1); // 触发捏合初始化:手指刚接触或首次进入双指状态 if (touchZero.phase == TouchPhase.Began || touchOne.phase == TouchPhase.Began || !_isPinching) { _initialPinchDistance = Vector2.Distance(touchZero.position, touchOne.position); _initialCameraDistance = _distance; _isPinching = true; // 清空历史距离数组,避免旧数据干扰 System.Array.Clear(_pinchDistances, 0, _pinchFramesCount); _pinchFramesIndex = 0; } // 计算当前捏合比例,转换为相机距离 float currentPinchDistance = Vector2.Distance(touchZero.position, touchOne.position); float pinchScale = currentPinchDistance / _initialPinchDistance; // 用初始相机距离除以比例,实现捏合放大/缩小 _distance = Mathf.Clamp(_initialCameraDistance / pinchScale, _distanceMin, _distanceMax); } else if (Input.GetMouseButton(0)) { // 鼠标旋转逻辑保留 _velocityX += _xSpeed * Input.GetAxis("Mouse X") * _distance * 0.02f; _velocityY += _ySpeed * Input.GetAxis("Mouse Y") * 0.02f; } else { // 无触摸时重置捏合状态 _isPinching = false; } // 旋转与相机位置更新逻辑保留 _rotationYAxis += _velocityX; _rotationXAxis -= _velocityY; _rotationXAxis = ClampAngle(_rotationXAxis, _yMinLimit, _yMaxLimit); Quaternion rotation = Quaternion.Euler(_cameraAngle, _rotationYAxis, 0); // 鼠标滚轮缩放逻辑保留 _distance = Mathf.Clamp(_distance - Input.GetAxis("Mouse ScrollWheel") * _pinchZoomSensitivity, _distanceMin, _distanceMax); Vector3 negDistance = new Vector3(0.0f, 0.0f, -_distance); Vector3 position = rotation * negDistance + _target.position; transform.rotation = rotation; transform.position = position; _velocityX = Mathf.Lerp(_velocityX, 0, Time.deltaTime * _smoothTime); _velocityY = Mathf.Lerp(_velocityY, 0, Time.deltaTime * _smoothTime); } }
核心修改说明
- 初始状态记录:每次捏合开始时,记录当前手指间距和相机的
_distance值,确保缩放基于当前相机位置 - 比例计算替代帧差累加:用当前手指间距与初始间距的比例计算相机距离,避免帧差累加导致的跳变和误差
- 状态重置:无触摸输入时重置
_isPinching并清空历史距离数组,确保下一次捏合不受上一次数据影响
修改后,无论小幅度还是大幅度捏合,相机都会从当前位置平滑缩放,不会出现跳转到最大范围的问题。
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

