Unity Pong:我的AI Paddle为何抖动?求修复方案
修复AI Paddle抖动问题的方案
问题根源
你的AI Paddle抖动主要来自四个原因:
- 浮点数精度误差:直接用
velocity != Vector2.zero判断球是否运动,会因为物理引擎的浮点数精度问题出现误判; - 硬切换运动状态:每次帧直接设置
rigidBody.velocity为固定速度或零,没有平滑过渡,导致刚体瞬间改变运动状态产生抖动; - 频繁获取组件:每次
FixedUpdate都调用theBall.GetComponent<Rigidbody2D>(),既影响性能也可能导致状态读取不稳定; - 死区范围过小:±0.2的位置判断区间太窄,球的微小位置变化就会触发AI在停止和移动之间反复切换。
修复步骤
- 缓存球的Rigidbody组件:在
Start方法中提前获取并缓存,避免重复调用GetComponent; - 改用平方模长判断运动状态:用
velocity.sqrMagnitude > 0.01代替直接和Vector2.zero比较,规避浮点数精度问题; - 平滑移动逻辑:使用
Mathf.MoveTowards计算目标位置,再通过MovePosition更新刚体位置,实现平滑移动; - 扩大死区范围:适当调整位置判断的阈值,减少状态切换频率。
修改后的完整代码
public class AIPaddle : MonoBehaviour { public GameObject theBall; public float speed = 10f; public float deadZone = 0.5f; // 扩大死区范围,可根据需求调整 private Rigidbody2D rigidBody; private Rigidbody2D ballRigidBody; // 缓存球的Rigidbody2D void Start() { rigidBody = GetComponent<Rigidbody2D>(); ballRigidBody = theBall.GetComponent<Rigidbody2D>(); // 提前缓存 } void FixedUpdate() { // 用平方模长判断球是否处于运动状态,避免浮点数精度问题 if (ballRigidBody.velocity.sqrMagnitude > 0.01f) { float targetY = theBall.transform.position.y; float currentY = transform.position.y; // 当球的位置超出死区范围时才移动 if (targetY > currentY + deadZone) { // 平滑移动到目标位置 float newY = Mathf.MoveTowards(currentY, targetY, speed * Time.fixedDeltaTime); rigidBody.MovePosition(new Vector2(transform.position.x, newY)); } else if (targetY < currentY - deadZone) { float newY = Mathf.MoveTowards(currentY, targetY, speed * Time.fixedDeltaTime); rigidBody.MovePosition(new Vector2(transform.position.x, newY)); } else { // 在死区内停止移动 rigidBody.velocity = Vector2.zero; } } else { // 球静止时AI也停止 rigidBody.velocity = Vector2.zero; } } }
额外优化建议
- 可以根据球的速度动态调整AI的移动速度,比如球速越快,AI反应越快,贴合你“玩家存活足够时长后可击败AI”的设计需求;
- 给AI添加加速度限制,避免瞬间达到最大速度,进一步减少抖动。
内容的提问来源于stack exchange,提问作者Charles Urban
相关产品推荐
相关产品推荐

