如何实现Unity Camera精灵宝可梦Go风格的Z轴触摸旋转
需求:实现《精灵宝可梦Go》风格的Unity相机触摸旋转效果
- 玩家做出圆形触摸手势时,相机同步向对应方向旋转
- 触摸回到起始点后,旋转仍持续进行
- 支持左右双向旋转
- 相机仅绕Z轴旋转,保持X轴90°、Y轴0°的固定角度
尝试的代码
if(Input.touchCount==1 && inputsPaused == false) { Touch firstTouch = Input.GetTouch(0); //if (firstTouch.deltaPosition.y > 0) //{ // if (firstTouch.deltaPosition.x < 0) // { // transform.eulerAngles += new Vector3(0, 0, -40f * Time.deltaTime); // compas.Rotate(new Vector3(0, 0, -4f * Time.deltaTime)); // } // else // if (firstTouch.deltaPosition.x > 0) // { // transform.eulerAngles += new Vector3(0, 0, 40f * Time.deltaTime); // compas.Rotate(new Vector3(0, 0, -4f * Time.deltaTime)); // } //} //else // if (firstTouch.deltaPosition.y < 0) //{ // if (firstTouch.deltaPosition.x < 0) // { // transform.eulerAngles += new Vector3(0, 0, 40f * Time.deltaTime); // compas.Rotate(new Vector3(0, 0, -4f * Time.deltaTime)); // } // else // if (firstTouch.deltaPosition.x > 0) // { // transform.eulerAngles += new Vector3(0, 0, -40f * Time.deltaTime); // compas.Rotate(new Vector3(0, 0, -4f * Time.deltaTime)); // } //} if (firstTouch.position.y > 0) { transform.eulerAngles += new Vector3(0, 0, -40f * Time.deltaTime); compas.Rotate(new Vector3(0, 0, -4f * Time.deltaTime)); } else if (firstTouch.position.y < 0) { transform.eulerAngles += new Vector3(0, 0, 40f * Time.deltaTime); compas.Rotate(new Vector3(0, 0, -4f * Time.deltaTime)); } text.text = "X: " + firstTouch.position.x + " Y: " + firstTouch.position.y; //if (Input.GetTouch(0).phase == TouchPhase.Began) //{ // startAngle = Mathf.Atan2(touchPos.y, touchPos.x) * Mathf.Rad2Deg; // if (startAngle <= 0) // { // startAngle += 360; // } //} //angle = Mathf.Atan2(touchPos.y, touchPos.x) * Mathf.Rad2Deg; //if (angle < 0) // angle += 360; //distanceAngle = startAngle - endAngle; //angle -= distanceAngle; //if (angle < 0) // angle += 360; //else if (angle > 360) // angle -= 360; //if (Input.GetTouch(0).phase == TouchPhase.Ended) //{ // endAngle = angle; //} //transform.rotation = Quaternion.Euler(transform.rotation.x, transform.rotation.y, angle); }
实现方案
核心逻辑
通过识别触摸圆周运动的方向(顺时针/逆时针)赋予相机持续旋转的角速度,触摸结束后通过衰减系数让旋转逐渐停止,同时严格锁定X、Y轴角度,避免偏移。
完整可运行代码
using UnityEngine; public class CameraTouchRotator : MonoBehaviour { [Header("旋转参数")] public float rotationSpeed = 60f; // 基础旋转速率 public float velocityDamp = 0.95f; // 触摸结束后角速度衰减系数(0~1,值越大旋转持续越久) public Transform compass; // 同步旋转的指南针对象(无需则留空) private float currentZAngle; // 记录当前Z轴旋转角度 private float rotationVelocity = 0f; // 相机旋转角速度 private Vector2 lastTouchPosition; // 上一帧触摸位置 private bool isTouchActive = false; void Start() { // 初始化相机角度,锁定X=90°、Y=0° currentZAngle = transform.eulerAngles.z; transform.eulerAngles = new Vector3(90f, 0f, currentZAngle); } void Update() { if (Input.touchCount == 1) { Touch touch = Input.GetTouch(0); switch (touch.phase) { case TouchPhase.Began: isTouchActive = true; lastTouchPosition = touch.position; rotationVelocity = 0f; // 触摸开始时重置角速度 break; case TouchPhase.Moved: // 计算触摸移动向量 Vector2 delta = touch.position - lastTouchPosition; // 通过叉积判断圆周方向:逆时针返回1,顺时针返回-1 float direction = Mathf.Sign(delta.x * touch.position.y - delta.y * touch.position.x); // 设置当前旋转角速度 rotationVelocity = direction * rotationSpeed; // 更新上一帧触摸位置 lastTouchPosition = touch.position; break; case TouchPhase.Ended: case TouchPhase.Canceled: isTouchActive = false; break; } } // 更新相机旋转状态 if (isTouchActive || rotationVelocity != 0f) { currentZAngle += rotationVelocity * Time.deltaTime; // 强制锁定X、Y轴角度,仅更新Z轴 transform.eulerAngles = new Vector3(90f, 0f, currentZAngle); // 同步旋转指南针(无需可删除此段) if (compass != null) { compass.Rotate(0f, 0f, -rotationVelocity * 0.1f * Time.deltaTime); } // 触摸结束后衰减角速度,直到停止 if (!isTouchActive) { rotationVelocity *= velocityDamp; if (Mathf.Abs(rotationVelocity) < 0.1f) { rotationVelocity = 0f; } } } } }
代码说明
- 圆周手势识别:使用触摸位置与移动向量的叉积判断旋转方向,避免直线滑动误触发
- 持续旋转机制:触摸时直接设置角速度,触摸结束后通过衰减系数实现自然减速停止,还原Pokemon Go的操作手感
- 角度锁定:每次更新旋转时强制设置X=90°、Y=0°,确保相机不会偏离指定姿态
- 参数可调:在Inspector面板可调整旋转速度和衰减系数,适配不同设备的操作灵敏度
使用步骤
- 将脚本挂载到目标相机对象上
- 若需同步旋转指南针,将指南针对象拖入
compass字段(无需则留空) - 在Inspector面板调整
rotationSpeed和velocityDamp参数至合适手感
内容的提问来源于stack exchange,提问作者Bogdan Radoi
相关产品推荐
相关产品推荐

