Vector3.MoveTowards实现跟随光标移动时无法触发2D碰撞检测怎么办?
解决方案
问题原因
直接通过transform.position赋值移动物体,相当于绕开了Unity 2D物理引擎的计算流程,物理引擎无法感知物体的移动路径,速度较快时会直接跳过碰撞体,导致碰撞回调无法触发。
前置配置检查
- 飞机节点必须挂载
Rigidbody2D组件,同时挂载对应形状的碰撞体(如BoxCollider2D/PolygonCollider2D),不要勾选碰撞体的Is Trigger属性 - 与飞机碰撞的目标物体必须挂载碰撞体,若目标为场景静态障碍物无需加刚体,若为动态物体也需要挂载
Rigidbody2D - 调整
Rigidbody2D属性:- Gravity Scale设为0,避免飞机受重力影响下坠
- Body Type设为Dynamic,Kinematic类型刚体无法与静态碰撞体触发碰撞回调
- 若移动速度非常快,可将Collision Detection改为Continuous,开启连续碰撞检测避免穿模
代码修改方案
将移动逻辑从Update移到物理更新周期的FixedUpdate中,通过Rigidbody2D提供的方法控制移动与旋转,保证物理引擎参与全部计算:
public float speed = 5f; public float rotationOffset = -90f; private Rigidbody2D rb; private void Awake() { // 获取刚体组件引用 rb = GetComponent<Rigidbody2D>(); } private void Update() { // 角度计算保留在Update,保证旋转响应跟手 Vector3 mousePos = Input.mousePosition; Vector3 objectPos = Camera.main.WorldToScreenPoint(transform.position); mousePos.x -= objectPos.x; mousePos.y -= objectPos.y; float angle = Mathf.Atan2(mousePos.y, mousePos.x) * Mathf.Rad2Deg; // 改用刚体方法控制旋转 rb.MoveRotation(angle + rotationOffset); } private void FixedUpdate() { // 移动逻辑放在FixedUpdate,和物理更新同步 Vector3 targetPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); targetPos.z = 0; // 用刚体MovePosition替代直接修改transform.position Vector2 newPos = Vector3.MoveTowards(rb.position, targetPos, speed * Time.fixedDeltaTime); rb.MovePosition(newPos); if (Vector2.Distance(rb.position, targetPos) < 0.01f) { Die(); } } private void Die() { // 此处保留原有的销毁逻辑 } private void OnCollisionEnter2D(Collision2D col) { Debug.Log("hit: " + col.gameObject.name); }
额外注意事项
- 确保飞机和碰撞目标的Z轴差值不超过0.01,2D碰撞体默认厚度极小,Z轴相差过大也会导致检测失效
- 不要同时在代码里修改transform的位置/旋转和刚体的位置/旋转,两者冲突会导致物理计算异常
内容的提问来源于stack exchange,提问作者NATHAN TOLLEY
相关产品推荐
相关产品推荐

