Unity 2D俯视角游戏玩家冲刺距离不一致问题修复求助
修复2D俯视角游戏触屏固定距离冲刺问题
当前冲刺逻辑的核心问题是依赖固定时长停止冲刺,计算方式为5 / dashSpeed。理论上移动距离为5单位,但实际中Rigidbody2D的移动会受物理引擎帧率、碰撞检测、刚体属性(如摩擦力)等因素干扰,导致实际移动距离与预期偏差,从而出现来回冲刺无法回到初始位置的情况。
以下是两种修复方案:
方案1:基于物理交互的固定距离冲刺
保留物理引擎交互(如碰撞后停止),通过实时检测移动距离确保冲刺到目标位置:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { private Vector2 touchStartPos; private Rigidbody2D rb; public float dashSpeed = 10f; // 自定义固定冲刺距离 public float dashDistance = 5f; void Start() { rb = GetComponent<Rigidbody2D>(); } void Update() { if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) { touchStartPos = Input.GetTouch(0).position; } if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended) { Vector2 touchEndPos = Input.GetTouch(0).position; Vector2 swipeDirection = touchEndPos - touchStartPos; if (swipeDirection.magnitude > 50f) { // 锁定到上下左右四个方向 swipeDirection = Mathf.Abs(swipeDirection.x) > Mathf.Abs(swipeDirection.y) ? new Vector2(Mathf.Sign(swipeDirection.x), 0f) : new Vector2(0f, Mathf.Sign(swipeDirection.y)); StartCoroutine(DashCoroutine(swipeDirection)); } } } IEnumerator DashCoroutine(Vector2 direction) { Vector2 startPosition = rb.position; Vector2 targetPosition = startPosition + direction * dashDistance; rb.velocity = direction * dashSpeed; // 实时检测是否接近目标位置 while (Vector2.Distance(rb.position, targetPosition) > 0.1f) { yield return null; } // 精准修正到目标位置并停止 rb.MovePosition(targetPosition); rb.velocity = Vector2.zero; } }
方案2:无物理干扰的平滑固定距离冲刺
若不需要冲刺过程中的物理交互(如碰撞响应),直接通过位置插值实现绝对精准的固定距离冲刺:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { private Vector2 touchStartPos; private Rigidbody2D rb; public float dashDuration = 0.2f; // 冲刺动画时长 public float dashDistance = 5f; void Start() { rb = GetComponent<Rigidbody2D>(); } void Update() { if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began) { touchStartPos = Input.GetTouch(0).position; } if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended) { Vector2 touchEndPos = Input.GetTouch(0).position; Vector2 swipeDirection = touchEndPos - touchStartPos; if (swipeDirection.magnitude > 50f) { // 锁定到上下左右四个方向 swipeDirection = Mathf.Abs(swipeDirection.x) > Mathf.Abs(swipeDirection.y) ? new Vector2(Mathf.Sign(swipeDirection.x), 0f) : new Vector2(0f, Mathf.Sign(swipeDirection.y)); StartCoroutine(SmoothDashCoroutine(swipeDirection)); } } } IEnumerator SmoothDashCoroutine(Vector2 direction) { Vector2 startPosition = rb.position; Vector2 targetPosition = startPosition + direction * dashDistance; float elapsedTime = 0f; // 平滑插值移动到目标位置 while (elapsedTime < dashDuration) { elapsedTime += Time.deltaTime; float t = elapsedTime / dashDuration; // 用SmoothStep实现更自然的加速减速效果 rb.MovePosition(Vector2.Lerp(startPosition, targetPosition, Mathf.SmoothStep(0f, 1f, t))); yield return null; } // 确保最终位置精准 rb.MovePosition(targetPosition); } }
关键改进说明
- 两种方案都优化了方向处理逻辑,直接生成精准的单位方向向量,避免Normalize带来的精度损耗。
- 方案1保留物理交互,适合需要碰撞响应的场景;方案2完全脱离物理引擎干扰,适合对移动精度要求极高的场景。
内容的提问来源于stack exchange,提问作者user20905443
相关产品推荐
相关产品推荐

