Unity火箭着陆游戏碰撞检测失效问题求助
一、核心设置问题(最可能的触发失效原因)
脚本挂载位置错误
你的LandingBehaviour脚本如果挂载在Rocket物体上,而Rocket本身没有Collider,碰撞事件不会触发在Rocket的脚本上——尽管Rocket有Rigidbody,但碰撞发生在子物体Thruster/RocketBody的Collider上。Unity中碰撞事件优先发送给碰撞体所在的物体,带Rigidbody的父物体若无自身Collider,可能无法触发碰撞事件。
修复:将脚本挂载到Thruster或RocketBody上,或者给Rocket添加与火箭形状匹配的Collider(比如Box Collider)。碰撞体初始重叠问题
若场景初始化时,火箭子物体的Collider与着陆台/地面的Collider已重叠,Unity会跳过初始碰撞事件的触发。
修复:调整火箭初始位置,确保所有Collider在游戏启动时无重叠。
二、代码逻辑错误(即使碰撞触发也无法正常工作)
碰撞标签判断逻辑完全错误
原代码中:if (!collision.gameObject.CompareTag("LandingPad") || !collision.gameObject.CompareTag("Ground")) { return; }用
||(逻辑或)意味着只要碰撞对象不是着陆台,或者不是地面,就直接返回。但任何对象不可能同时是着陆台和地面,因此这个条件永远为true,会直接跳过后续所有逻辑。
修复:改为&&(逻辑与),表示既不是着陆台也不是地面时才返回:if (!collision.gameObject.CompareTag("LandingPad") && !collision.gameObject.CompareTag("Ground")) { return; }冻结刚体的代码写反
你需要碰撞后冻结运动,应将Rigidbody设为运动学,但原代码写的是:_rigidBody.isKinematic = false;修复:改成
true:_rigidBody.isKinematic = true;着陆台类型判断逻辑错误
原脚本中_greenPad/_yellowPad/_redPad属于挂载脚本的物体(比如火箭),而非碰撞到的着陆台,逻辑完全不符合需求。
修复:给不同颜色的着陆台分别设置标签(如GreenPad、YellowPad、RedPad),碰撞时直接判断标签:if (collision.gameObject.CompareTag("GreenPad")) { Debug.Log("Green Landing Pad Found."); _score *= 2; } else if (collision.gameObject.CompareTag("YellowPad")) { Debug.Log("Yellow Landing Pad Found."); _score *= 3; } else if (collision.gameObject.CompareTag("RedPad")) { Debug.Log("Red Landing Pad Found."); _score *= 5; }旋转判断单位错误
transform.rotation.z获取的是四元数分量(范围[-1,1]),不是角度值。需转换成欧拉角的z轴角度:float zAngle = collision.gameObject.transform.eulerAngles.z; // 转换为-180到180的角度范围 zAngle = (zAngle > 180) ? zAngle - 360 : zAngle; if (Mathf.Abs(zAngle) >= 45) { _crash = true; }
三、完整修复后的代码示例
using UnityEngine; public class LandingBehaviour : MonoBehaviour { private bool _crash = false; private float _score = 1; [SerializeField] private Rigidbody _rigidBody; private void Awake() { // 若脚本挂载在子物体,自动获取父物体的Rigidbody if (_rigidBody == null) { _rigidBody = GetComponentInParent<Rigidbody>(); } } private void OnCollisionEnter(Collision collision) { Debug.Log("A collision has occurred."); // 冻结刚体,停止所有物理运动 _rigidBody.isKinematic = true; // 过滤非目标碰撞对象 if (!collision.gameObject.CompareTag("GreenPad") && !collision.gameObject.CompareTag("YellowPad") && !collision.gameObject.CompareTag("RedPad") && !collision.gameObject.CompareTag("Ground")) { return; } // 判断着陆台是否倾斜过度 float zAngle = collision.gameObject.transform.eulerAngles.z; zAngle = (zAngle > 180) ? zAngle - 360 : zAngle; if (Mathf.Abs(zAngle) >= 45) { _crash = true; } // 计算得分 if (collision.gameObject.CompareTag("GreenPad")) { Debug.Log("Green Landing Pad Found."); _score *= 2; } else if (collision.gameObject.CompareTag("YellowPad")) { Debug.Log("Yellow Landing Pad Found."); _score *= 3; } else if (collision.gameObject.CompareTag("RedPad")) { Debug.Log("Red Landing Pad Found."); _score *= 5; } else if (collision.gameObject.CompareTag("Ground")) { Debug.Log("Ground Found."); _score *= 1; } // 此处添加显示得分、重试/退出按钮的逻辑 // ShowScorePanel(); // ShowControlButtons(); } }
最后验证步骤
- 将脚本挂载到
Thruster或RocketBody上,或给Rocket添加自身Collider - 给不同颜色着陆台设置对应标签(
GreenPad/YellowPad/RedPad),地面设置Ground标签 - 运行游戏,查看Console是否输出碰撞日志,检查刚体是否冻结
- 测试不同着陆台的得分计算是否正确
内容的提问来源于stack exchange,提问作者RyanJ

