Unity挂载同一Player C#脚本的3D对象运行时其余被销毁问题求助
多挂载Player脚本后仅保留单个对象的常见成因排查
最高概率触发原因:脚本内置错误单例逻辑
这是该类问题90%以上的诱因,错误写法通常长这样:
public class Player : MonoBehaviour { // 静态单例引用 public static Player Instance; private void Awake() { // 只要检测到已经存在单例实例,就直接销毁当前挂载的对象 if (Instance != null) { Destroy(gameObject); } else { Instance = this; } } }
- 这类逻辑的设计初衷是保证全局唯一Player实例,但没有考虑多对象同场景挂载的测试场景,只要挂载第二个及以上的Player脚本,新对象就会在
Awake阶段检测到已经存在的静态单例引用,直接触发自销毁,最终只保留最早初始化的那个对象。 - 隐蔽变种:在
Start/OnEnable方法中通过FindObjectsOfType<Player>()遍历所有同脚本对象,只要数量超过1就销毁当前对象,单挂载时因为检测不到多余对象所以不会触发异常。
次高概率触发原因:跨场景保留逻辑配套错误
如果在单例逻辑中搭配了DontDestroyOnLoad(gameObject)的跨场景保留逻辑,会进一步放大该问题:新场景中生成的所有Player对象,都会被旧场景遗留的单例判定为"多余实例"直接销毁,视觉上和同场景多挂载导致的销毁效果完全一致。
快速定位方法
- 在脚本中所有调用
Destroy()的行打上断点,运行场景后观察哪段代码触发了对Player对象的销毁 - 临时清空Player脚本中所有和对象销毁、单例初始化相关的逻辑,重新挂载2个Player对象测试,排除脚本内部逻辑干扰
- 排查项目中其他全局脚本,是否存在批量查找所有Player对象、仅保留单个实例的强制销毁逻辑
定位销毁来源的实用小技巧:
在Player脚本中添加OnDestroy回调输出堆栈信息,可以直接精准定位是哪段代码触发了销毁操作,无需逐行排查:private void OnDestroy() { Debug.LogError($"Player对象被销毁,调用堆栈:{System.Environment.StackTrace}"); }
内容的提问来源于stack exchange,提问作者Vamaka12
相关产品推荐
相关产品推荐

