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;
卡顿原因
- 输入处理时机错误:触摸输入逻辑放在
FixedUpdate执行。FixedUpdate是固定时间间隔调用,而触摸的deltaPosition是基于帧时间的,两者不同步会导致输入延迟,快速滑动时输入数据堆积,造成移动不连贯。 - 滑动状态逻辑混乱:
isSwiping的切换逻辑有问题——触摸移动时刚设为true,紧接着判断位置相等就改回false,导致只有单次帧能触发移动,快速滑动时大量输入被丢弃,直接表现为卡顿。 - 未适配帧时间:移动计算用固定系数
movementSpeed,没乘以Time.deltaTime,不同帧率下移动速度不一致,快速滑动时帧率波动会放大卡顿感。 - 移动方式冲突:同时用
transform.position改X轴位置和Rigidbody.velocity控制Z轴前进,两种方式混用会导致刚体物理状态不一致,引发抖动卡顿。
解决方法
- 移输入逻辑到
Update:Update每帧调用,能及时响应触摸输入,避免输入延迟和数据堆积。 - 修正滑动状态管理:在
TouchPhase.Began标记滑动开始,TouchPhase.Ended/Canceled标记结束,确保整个触摸过程都能响应移动。 - 添加帧时间适配:移动计算时乘以
Time.deltaTime,保证不同帧率下移动速度一致。 - 统一用刚体控制: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
相关产品推荐
相关产品推荐

