Unity C#开发Pong游戏 小球碰撞玩家后无法反弹问题
问题根因
- 小球移动完全通过
Update内直接修改transform.position实现,全程没有调用Rigidbody2D的物理移动接口,rb.velocity始终为0,存储的lastVelocity一直是零向量,反弹方向计算从根源上无效。 - 碰撞回调中仅计算了反射方向和速度值,没有将计算结果赋值回刚体,计算逻辑执行完就被丢弃,没有实际作用到小球运动上。
- 直接修改坐标的移动方式会绕过物理引擎的碰撞反馈流程,哪怕碰撞事件被触发,也不会产生物理引擎自带的反弹效果。
修复步骤
1. 调整小球移动逻辑
删除原BallCode中直接修改position的代码,改用刚体驱动小球运动,所有物理相关逻辑放到FixedUpdate生命周期中执行,保证物理计算帧率稳定:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BallCode : MonoBehaviour { private Rigidbody2D rb; public float ballSpeed = 5.8f; void Start() { rb = GetComponent<Rigidbody2D>(); // 开局给小球一个初始向左的速度,可根据需求调整初始方向 rb.velocity = Vector2.left * ballSpeed; } void FixedUpdate() { // 持续锁定小球速度,避免碰撞后出现速度衰减 if(rb.velocity.magnitude != ballSpeed) { rb.velocity = rb.velocity.normalized * ballSpeed; } } }
注意:提前检查小球挂载的Rigidbody2D组件,将Gravity Scale参数设为0,避免小球受重力影响下落;小球、玩家挡板、边界的Collider2D组件都不要勾选Is Trigger选项。
2. 补全反弹逻辑的赋值操作
修改BallBounce脚本,补全刚体速度赋值逻辑,将速度读取逻辑移到FixedUpdate中避免帧率波动导致取值错误:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BallBounce : MonoBehaviour { private Rigidbody2D rb; Vector2 lastVelocity; void Awake() { rb = GetComponent<Rigidbody2D>(); } void FixedUpdate() { lastVelocity = rb.velocity; } private void OnCollisionEnter2D(Collision2D coll) { float speed = lastVelocity.magnitude; Vector2 direction = Vector2.Reflect(lastVelocity.normalized, coll.contacts[0].normal); // 之前遗漏的核心步骤:将计算后的反弹速度赋值给刚体 rb.velocity = direction * speed; } }
注意:如果两个脚本同时挂载在小球上,建议将速度参数统一管理,避免两个脚本的速度值不一致导致运动异常;也可以直接把两段逻辑合并到同一个脚本中减少冗余。
3. 玩家对象配置调整
现有Player控制代码不需要修改,只需给玩家对象挂载Rigidbody2D组件,将Body Type设置为Kinematic(运动学刚体,不受物理力影响,只响应碰撞检测),Gravity Scale设为0即可正常触发碰撞反弹。
内容的提问来源于stack exchange,提问作者Yetam
相关产品推荐
相关产品推荐

