Unity中订阅自定义C#事件后函数无法执行的原因排查
嘿,我看了你贴的UIManager代码片段,结合平时踩过的坑,给你梳理几个常见的原因,帮你排查为什么订阅事件后函数没执行:
事件压根没触发
你定义了OnSwitchCargoOverview这个Action,但代码里没看到触发它的逻辑(也就是OnSwitchCargoOverview?.Invoke(true);这类调用)。先确认你是不是在某个地方调用了Invoke方法——如果事件都没被触发,订阅的函数自然不会跑起来。单例实例出问题了
你的UIManager用了单例模式,但这里有几个容易踩的坑:- 如果场景里存在多个UIManager对象,第二个会被销毁。要是你的订阅代码不小心绑在了被销毁的那个实例上,那订阅关系直接就没了。
- 要是订阅代码在Awake阶段执行,但UIManager的Awake执行顺序比订阅者晚,那订阅的时候
instance还没初始化,等于订阅到了空对象上。可以试试调整脚本执行顺序,或者把订阅逻辑放在Start里。
订阅者对象状态异常
假设你在某个MonoBehaviour脚本里订阅了事件,比如:void Start() { UIManager.instance.OnSwitchCargoOverview += OnCargoOverviewSwitched; } void OnCargoOverviewSwitched(bool isActive) { // 你的逻辑代码 }如果这个脚本所在的GameObject被销毁、禁用,或者脚本本身被禁用了,那订阅的函数肯定不会执行。先检查订阅者的对象状态是否正常。
事件被意外覆盖成null
注意别直接给OnSwitchCargoOverview赋值(比如OnSwitchCargoOverview = someMethod;),这会直接覆盖之前所有的订阅。一定要用+=添加订阅,-=取消订阅。如果不小心用了赋值操作,之前的订阅就全部失效了。订阅时机太晚
如果事件在你订阅之前就已经触发了,那订阅的函数自然不会响应。比如UIManager在Start里就触发了事件,但订阅者的Start执行顺序更晚,等你订阅的时候事件已经跑完了。可以调整订阅时机(比如把订阅放在Awake里,确保单例已经初始化),或者延迟事件的触发时机。
给你个正确的示例参考:
首先在UIManager里加个触发事件的方法:
public void TriggerCargoOverviewSwitch(bool isActive) { // 用?.避免空引用异常 OnSwitchCargoOverview?.Invoke(isActive); }
然后在需要触发的地方调用:
UIManager.instance.TriggerCargoOverviewSwitch(true);
订阅者这边最好在OnEnable/OnDisable里处理订阅和取消订阅,避免内存泄漏:
void OnEnable() { if (UIManager.instance != null) { UIManager.instance.OnSwitchCargoOverview += OnCargoOverviewSwitched; } } void OnDisable() { if (UIManager.instance != null) { UIManager.instance.OnSwitchCargoOverview -= OnCargoOverviewSwitched; } } void OnCargoOverviewSwitched(bool isActive) { // 你的业务逻辑 Debug.Log($"Cargo overview switched to: {isActive}"); }
备注:内容来源于stack exchange,提问作者Eric Hu

