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

如何实现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面板可调整旋转速度和衰减系数,适配不同设备的操作灵敏度

使用步骤

  1. 将脚本挂载到目标相机对象上
  2. 若需同步旋转指南针,将指南针对象拖入compass字段(无需则留空)
  3. 在Inspector面板调整rotationSpeed和velocityDamp参数至合适手感

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 01:48:28