Unity第三人称移动端相机首次拖拽旋转跳变问题求助
问题解决:移动端第三人称相机首次拖拽跳变旋转
问题根源
你遇到的首次拖拽跳变,是因为坐标坐标系不匹配:
OnPointerDown中存储的是屏幕全局坐标eventData.position- 但
OnDrag里计算拖拽增量时,用的是触摸区域的本地坐标localPointerPosition
两者坐标系完全不同,首次计算的delta值会异常大,直接导致相机跳变旋转。每次抬起指针后再次按下,都会重复这个错误。
修复方案
在OnPointerDown时,就将触摸点转换为触摸区域的本地坐标,存储到lastDragPosition中,确保后续计算增量时坐标系统一。另外,初始化xAxis和yAxis时,读取相机当前的欧拉角,避免初始值与实际相机旋转不一致的问题。
修改后的完整代码
using UnityEngine; using UnityEngine.EventSystems; public class CameraMobile2 : MonoBehaviour, IDragHandler, IPointerDownHandler, IPointerUpHandler { public float rotationSpeed; private float xAxis; private float yAxis; private float minRotation = 10f; private float maxRotation = 60f; public Transform playerHead; public Transform cameraTransform; public RectTransform touchpadRect; private bool isDragging = false; private Vector2 lastDragPosition; private void Start() { // 初始化时读取相机当前的旋转值,避免初始偏差 xAxis = cameraTransform.eulerAngles.x; yAxis = cameraTransform.eulerAngles.y; // 处理x轴欧拉角可能的360度循环问题(比如相机初始旋转是350度,实际是-10度) if (xAxis > 180f) { xAxis -= 360f; } xAxis = Mathf.Clamp(xAxis, minRotation, maxRotation); } public void OnPointerDown(PointerEventData eventData) { isDragging = true; // 将屏幕坐标转换为触摸区域的本地坐标后存储 RectTransformUtility.ScreenPointToLocalPointInRectangle(touchpadRect, eventData.position, null, out lastDragPosition); Debug.Log("pointer Down"); } public void OnDrag(PointerEventData eventData) { Debug.Log("pointer drag"); if (!isDragging) { return; } Vector2 localPointerPosition; if (RectTransformUtility.ScreenPointToLocalPointInRectangle(touchpadRect, eventData.position, null, out localPointerPosition)) { Vector2 delta = localPointerPosition - lastDragPosition; lastDragPosition = localPointerPosition; yAxis += delta.x * rotationSpeed * Time.deltaTime; xAxis -= delta.y * rotationSpeed * Time.deltaTime; xAxis = Mathf.Clamp(xAxis, minRotation, maxRotation); Vector3 targetRotation = new Vector3(xAxis, yAxis); cameraTransform.eulerAngles = targetRotation; } } public void OnPointerUp(PointerEventData eventData) { Debug.Log("pointer Up"); isDragging = false; } private void Update() { cameraTransform.position = playerHead.position - cameraTransform.forward * 2f; } }
额外说明
Start方法中初始化xAxis和yAxis,是为了让相机的初始旋转和代码中的累积变量保持一致,避免首次运行时相机突然跳到(0,0)旋转。- 处理x轴欧拉角的360度循环问题,是因为Unity中欧拉角会以0-360度循环,而我们需要的是min到max范围内的数值,避免出现异常。
内容的提问来源于stack exchange,提问作者Rehan Younas
相关产品推荐
相关产品推荐

