Unity天体模拟中无Destroy调用的GameObject运行时自行销毁问题
问题根因分析
- 核心逻辑冲突:
Gravity脚本在触发区内给行星施加引力,但PlanetVelocity的Update方法直接覆盖rb.velocity赋值,两者逻辑完全互斥,所有引力计算实际无效,速度全由错误的计算公式控制。 - 速度计算错误:环绕速度的正确公式是
v = sqrt(G*M/r),但你的代码里用dif.sqrMagnitude(距离的平方)作为半径r代入计算,同时错误引入了引力值_gravity.f做参数,最终算出来的速度要么大到直接把行星甩出轨道,要么小到让行星直接坠向太阳。 - 小质量行星优先出问题的原因:质量最小的天体缩放后刚体质量仅0.3左右,受错误速度值的影响远大于大质量行星,会最先飞出摄像机远裁剪面不可见(你误以为被销毁),或者率先触碰到太阳的碰撞体被隐藏/移除。
- 潜在空引用隐患:
Gravity类中全局定义了m2变量,但OnTriggerStay内重复定义了局部m2,全局m2始终为空,你未开启Debug模式所以没有抛出空引用报错。
修复方案
- 统一物理逻辑,二选一即可:
- 方案A(纯运动模拟):删掉
Gravity脚本的引力施加逻辑,仅靠PlanetVelocity计算正确的环绕速度赋值 - 方案B(物理模拟):删掉
PlanetVelocity中Update内所有覆盖rb.velocity的代码,仅保留初始速度赋值,引力完全交给Gravity脚本计算,推荐选此方案模拟效果更真实。
- 方案A(纯运动模拟):删掉
- 修正初始速度计算:在
PlanetVelocity的Start方法中添加初始切向速度代码,替换原有错误的Update速度逻辑:void Start() { _gravity = FindObjectOfType<Gravity>(); rb = GetComponent<Rigidbody>(); rb.mass = mass * massScale; // 计算正确的初始环绕速度 float initDistance = Vector3.Distance(transform.position, Sun.transform.position); float initV = Mathf.Sqrt(_gravity.G * _gravity.m1.mass / initDistance); // 施加垂直于日星连线的切向速度 rb.velocity = transform.right * initV; } - 修正
Gravity脚本冗余定义:删掉类全局的private Rigidbody m2;声明,避免空引用报错。 - 项目配置调整:
- 打开
Edit > Project Settings > Physics,将Sleep Threshold调整为0.0001,防止小质量刚体因受力过小被系统休眠停转。 - 将主摄像机的
Far Clip Plane参数调大到覆盖所有行星轨道范围,避免天体飞远后不可见。 - 确认太阳的碰撞体勾选了
Is Trigger,若存在碰撞销毁逻辑可以先临时关闭排查。
- 打开
内容的提问来源于stack exchange,提问作者Charlie Hayward
相关产品推荐
相关产品推荐

