Unity继承BasePanel的面板OnExit方法执行异常求助
面板栈Pop操作异常排查
问题背景
用栈存储所有继承BasePanel类的面板对象,所有面板均继承BasePanel并包含虚方法OnExit。流程为:面板OnEnter阶段绑定按钮点击事件,点击后调用PanelManage.Pop,Pop方法会调用栈顶面板的OnExit。
首个面板点击后能正常执行OnExit并销毁,但第二个PrefectProfile面板点击调用Pop时,控制台能显示Pop内的Debug日志,却无OnExit的日志输出,面板也未销毁。两个面板继承自同一父类,逻辑一致,排查多时未找到原因。
核心代码
栈定义
private Stack<BasePanel> stackPanels;
BasePanel的虚方法OnExit
public virtual void OnExit() { Debug.Log("UITypeName= "+UIType.Name); UIManage.DestoryUI(UIType); }
初始面板的OnEnter实现
public override void OnEnter() { UITool.GetOrAddComponentsInChildren<Button>("Next").onClick.AddListener(() => { PanelManage.Pop(); PanelManage.Push(new PrefectProfile()); }); }
PrefectProfile面板的OnEnter实现
public override void OnEnter() { UITool.GetOrAddComponentsInChildren<Button>("SelectFile").onClick.AddListener(()=> { Debug.Log("Upload"); PanelManage.Pop(); }); UITool.GetOrAddComponentsInChildren<Button>("UploadLater").onClick.AddListener(() => { PanelManage.Pop(); PanelManage.Push(new IntroductionPanel()); }); }
PanelManage的Pop方法
public void Pop() { if (stackPanels.Count > 0) { stackPanels.Peek().OnExit(); Debug.Log(stackPanels.First()); stackPanels.Pop(); } if (stackPanels.Count > 0) stackPanels.Peek().OnResume(); }
排查方向
- 检查栈顶实例有效性:查看
Pop中Debug.Log(stackPanels.First())的输出内容,确认是否是预期的PrefectProfile实例。如果输出为null或其他对象,说明栈内对象被篡改或Push时未正确加入有效实例。 - 子类OnExit重写问题:确认
PrefectProfile是否重写了OnExit方法但未调用base.OnExit()。如果子类重写后跳过基类逻辑,基类的Debug日志和销毁操作都不会执行。 - UIType赋值验证:检查
PrefectProfile的UIType是否正确赋值。若UIType为null,UIType.Name会触发空引用异常,导致OnExit执行中断,可查看控制台是否有隐藏的异常日志(注意是否开启了忽略空引用的设置)。 - 按钮绑定与栈状态检查:确认
PrefectProfile的OnEnter是否被多次调用,导致按钮事件重复绑定,点击时多次执行Pop使栈提前为空。此外,每次Push新面板后,打印栈的Count和实例类型,验证栈状态是否符合预期。 - UIManage.DestoryUI逻辑排查:检查
DestoryUI方法是否对PrefectProfile对应的UIType有特殊判断逻辑,比如条件不满足导致销毁操作未执行,或者采用异步销毁但没有反馈。
内容的提问来源于stack exchange,提问作者aron kan
相关产品推荐
相关产品推荐

