Unity C#中EventHandler事件RefreshLevel判空作用及不触发问题咨询
1、if(RefreshLevel != null)的实际作用
C#中如果一个事件没有任何外部订阅者,它的默认值就是null,如果此时直接调用RefreshLevel(xxx,xxx)会直接抛出空引用异常导致程序崩溃。这行判断就是用来检查当前是否有方法订阅了RefreshLevel事件,只有存在订阅者时才会执行事件触发逻辑,避免报错。
现在C# 6及以上版本可以用更简洁的空条件调用写法代替:RefreshLevel?.Invoke(this, new LevelEventArgs(level));,效果和你写的if判断完全一致。
2、RefreshLevel的具体内容
你声明的public event EventHandler<LevelEventArgs> RefreshLevel;是一个标准的.NET泛型事件:
- 底层本质是一个委托容器,存储所有订阅了该事件的方法的引用,触发事件时会按订阅顺序依次执行所有存入的方法。
- 它的委托签名由
EventHandler<LevelEventArgs>约束:所有订阅该事件的方法都必须符合void 方法名(object 发送者, LevelEventArgs 事件参数)的格式,第一个参数是触发事件的实例(这里就是GameLevel的单例对象),第二个参数是你自定义的LevelEventArgs,用来传递当前等级数值。
3、该事件无法触发的常见原因
你可以按以下顺序排查:
- 事件触发的前置逻辑不满足
LevelUp方法根本没有被调用,触发事件的入口没执行Start方法中GameObject.Find("ItemWorld")查找失败,导致manyItem为0,burnedItem < manyItem的判断永远不成立,不会走到事件触发的代码分支- 调用
LevelUp时burnedItem已经大于等于manyItem,进入了else分支不会触发事件
- 订阅逻辑异常
- 订阅代码本身没有执行:比如订阅脚本没有挂载到激活的GameObject上、订阅代码写在未执行的分支里
- 订阅时机错误:比如在其他脚本的
Awake阶段就尝试通过GameLevel.current订阅事件,但此时GameLevel的Awake还未执行,current为null,订阅代码直接抛空失败 - 订阅后又执行了
-=操作取消了订阅,或者订阅时方法签名和事件要求的不匹配
- 单例异常
- 场景中挂载了多个
GameLevel脚本,current被后续Awake的实例覆盖,你订阅的是旧实例的事件,而实际调用LevelUp的是新实例 - 挂载
GameLevel的GameObject被销毁或禁用,current为空无法执行触发逻辑
- 场景中挂载了多个
内容的提问来源于stack exchange,提问作者Code_Sliver
相关产品推荐
相关产品推荐

