Unity中使用Mathf.PingPong实现敌人两点间来回移动失效求助
解决敌人两点间来回移动问题
- 调整
Mathf.PingPong的计算逻辑,让移动周期更可控,避免因参数设置不合理导致的视觉异常 - 若使用
Rigidbody2D,优先用其内置方法处理移动,避免与物理引擎冲突 - 初始时将物体定位到目标端点,消除初始位置带来的突兀过渡
修改后的代码(推荐版本)
public class Enemy : MonoBehaviour { public float moveDuration = 2.0f; // 单程移动所需时间(秒) public Vector2 pointA = new Vector2(9, 0); public Vector2 pointB = new Vector2(2, 0); Rigidbody2D rb; void Start() { rb = GetComponent<Rigidbody2D>(); rb.bodyType = RigidbodyType2D.Kinematic; // 设置为运动学刚体,避免物理干扰 transform.position = pointA; // 初始位置锚定到pointA } void FixedUpdate() // 物理相关操作使用FixedUpdate更稳定 { // PingPong返回0~2的循环值,除以2得到0~1的平滑过渡系数 float t = Mathf.PingPong(Time.time / moveDuration, 2) / 2; Vector2 targetPos = Vector2.Lerp(pointA, pointB, t); rb.MovePosition(targetPos); } }
关键调整说明
- moveDuration参数:替代原有的
movementSpeed,直接控制单程移动时间,逻辑更直观。比如设为2,代表2秒从A到B,再2秒返回,循环往复。 - FixedUpdate:处理刚体移动时使用该方法,匹配物理引擎的更新频率,避免移动卡顿。
- 刚体类型设置:将刚体设为运动学类型,既可以保持碰撞检测功能,又不会被其他物理力干扰移动轨迹。
保留原movementSpeed逻辑的替代方案
如果坚持用速度控制移动快慢,可通过计算两点距离来推导合理的PingPong参数:
public class Enemy : MonoBehaviour { public float movementSpeed = 5.0f; public Vector2 pointA = new Vector2(9, 0); public Vector2 pointB = new Vector2(2, 0); Rigidbody2D rb; float singleTripTime; void Start() { rb = GetComponent<Rigidbody2D>(); rb.bodyType = RigidbodyType2D.Kinematic; transform.position = pointA; // 计算单程移动所需时间:两点距离/移动速度 float distance = Vector2.Distance(pointA, pointB); singleTripTime = distance / movementSpeed; } void FixedUpdate() { float t = Mathf.PingPong(Time.time / singleTripTime, 2) / 2; Vector2 targetPos = Vector2.Lerp(pointA, pointB, t); rb.MovePosition(targetPos); } }
内容的提问来源于stack exchange,提问作者Justus Tate
相关产品推荐
相关产品推荐

