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

Unity玩家滑动移动卡顿问题:高速滑动卡顿加剧的原因与解决

滑动移动卡顿问题排查与解决

问题描述

我制作了一个沿Z轴以恒定速度前进的玩家对象,并为其添加了X轴左右滑动移动功能。但发现低速滑动时卡顿轻微,用力快速滑动时卡顿会明显加剧。请问该卡顿产生的原因是什么?该如何解决?


原代码

滑动移动脚本

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class swipeMovement : MonoBehaviour
{
    private float movementSpeed = 0.0055f;
    private Touch touch;
    Vector3 clampPos;
    public bool canswipe;
    private Vector3 initialTouchPosition;
    bool isSwiping;
    // Start is called before the first frame update
    void Start()
    {
        isSwiping = false;
        canswipe = false;
    }
 
    // Update is called once per frame
    void FixedUpdate()
    {
        swipeMove();
    }
 
    /* void Update()
     {
         if (canswipe)
         {
             HandleSwipeInput();
         }
     }
    /
     private void HandleSwipeInput()
     {
         if (Input.touchCount > 0)
         {
             Touch touch = Input.GetTouch(0);
 
             switch (touch.phase)
             {
                 case TouchPhase.Began:
                     initialTouchPosition = transform.position;
                     break;
 
                 case TouchPhase.Moved:
                     clampPos = new Vector3(
                         Mathf.Clamp(initialTouchPosition.x + touch.deltaPosition.x * movementSpeed, -2.2f, 2f),
                         transform.position.y,
                         transform.position.z
                     );
                     transform.position = clampPos;
                     break;
             }
         }
        */
       
    private void swipeMove()
    {
        if (canswipe)
        {
            if (isSwiping == false)
            {
                if (Input.touchCount > 0)
                {
                    touch = Input.GetTouch(0);

                    if (touch.phase == TouchPhase.Moved)
                    {
                        isSwiping = true;
                        clampPos = new Vector3(Mathf.Clamp(transform.position.x, -2.2f, 2f) + touch.deltaPosition.x * movementSpeed, transform.position.y, transform.position.z);
                        // transform.position = new Vector3(transform.position.x + touch.deltaPosition.x * movementSpeed, transform.position.y, transform.position.z);
                        transform.position = clampPos;
                    }

                    if (transform.position == clampPos)
                    {
                        isSwiping = false;
                    }
                }
            }
        }
    }
}

玩家Z轴前进代码

playerrb.velocity = transform.forward * PlayerSpeed;

卡顿原因

  1. 输入处理时机错误:触摸输入逻辑放在FixedUpdate执行。FixedUpdate是固定时间间隔调用,而触摸的deltaPosition是基于帧时间的,两者不同步会导致输入延迟,快速滑动时输入数据堆积,造成移动不连贯。
  2. 滑动状态逻辑混乱:isSwiping的切换逻辑有问题——触摸移动时刚设为true,紧接着判断位置相等就改回false,导致只有单次帧能触发移动,快速滑动时大量输入被丢弃,直接表现为卡顿。
  3. 未适配帧时间:移动计算用固定系数movementSpeed,没乘以Time.deltaTime,不同帧率下移动速度不一致,快速滑动时帧率波动会放大卡顿感。
  4. 移动方式冲突:同时用transform.position改X轴位置和Rigidbody.velocity控制Z轴前进,两种方式混用会导致刚体物理状态不一致,引发抖动卡顿。

解决方法

  1. 移输入逻辑到Update:Update每帧调用,能及时响应触摸输入,避免输入延迟和数据堆积。
  2. 修正滑动状态管理:在TouchPhase.Began标记滑动开始,TouchPhase.Ended/Canceled标记结束,确保整个触摸过程都能响应移动。
  3. 添加帧时间适配:移动计算时乘以Time.deltaTime,保证不同帧率下移动速度一致。
  4. 统一用刚体控制:X轴移动也通过Rigidbody.MovePosition或修改速度实现,避免直接改Transform和刚体逻辑冲突。

修正后的代码

滑动移动脚本

using UnityEngine;

public class SwipeMovement : MonoBehaviour
{
    [SerializeField] private float swipeSpeed = 5f;
    [SerializeField] private float xClampMin = -2.2f;
    [SerializeField] private float xClampMax = 2f;
    public bool canSwipe;
    private Rigidbody playerRb;
    private bool isSwiping;

    private void Awake()
    {
        playerRb = GetComponent<Rigidbody>();
    }

    private void Start()
    {
        isSwiping = false;
        canSwipe = false;
    }

    private void Update()
    {
        if (canSwipe)
        {
            HandleSwipeInput();
        }
    }

    private void HandleSwipeInput()
    {
        if (Input.touchCount > 0)
        {
            Touch touch = Input.GetTouch(0);

            switch (touch.phase)
            {
                case TouchPhase.Began:
                    isSwiping = true;
                    break;

                case TouchPhase.Moved:
                    if (isSwiping)
                    {
                        // 计算X轴移动量并适配帧时间
                        float moveX = touch.deltaPosition.x * swipeSpeed * Time.deltaTime;
                        Vector3 targetPos = playerRb.position + new Vector3(moveX, 0, 0);
                        // 限制X轴范围
                        targetPos.x = Mathf.Clamp(targetPos.x, xClampMin, xClampMax);
                        // 用刚体方法更新位置,保证物理一致性
                        playerRb.MovePosition(targetPos);
                    }
                    break;

                case TouchPhase.Ended:
                case TouchPhase.Canceled:
                    isSwiping = false;
                    break;
            }
        }
    }

    // Z轴前进控制整合到同一脚本
    [SerializeField] private float forwardSpeed = 10f;
    private void FixedUpdate()
    {
        // 只修改Z轴速度,保留X轴的刚体移动结果
        Vector3 currentVelocity = playerRb.velocity;
        currentVelocity.z = transform.forward.z * forwardSpeed;
        playerRb.velocity = currentVelocity;
    }
}

内容的提问来源于stack exchange,提问作者sumayya rashid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:17:46