事件分发未正确移除导致的看起来是变量值的问题

20 篇文章 1 订阅
3 篇文章 0 订阅

前言

今天在做飞机大战游戏的时候,遇到一个莫名其妙的bug。
部分代码如下:

public class FactoryPage : Page
{
	PlaneUnitType unitType;

    public FactoryPage(GameObject obj, Window window, params object[] paras) : base(obj, window)
    {
        this.unitType = (PlaneUnitType)paras[0];
    }
    public override void AddUIEventListener()
    {
        base.AddUIEventListener();
        EventDispatcher.Instance.AddListener(EventID.OnUpgradeUnit, onUpgradeUnit);        
    }
    public override void RemoveUIEventListener()
    {
        base.RemoveUIEventListener();
        EventDispatcher.Instance.RemoveListener(EventID.OnUpgradeUnit, onUpgradeUnit);
    }
}

/// <summary>
/// Page为Window窗口内的内部页面
/// </summary>
public class Page : UIRoot
{
    /// <summary>
    /// 该page归宿的Window
    /// </summary>
    public Window parentWindow;
    public Page(GameObject obj,Window window)
    {
        this.rootObj = obj;
        this.parentWindow = window;
        AutoLinkUI(this);
        Init();
        AddUIEventListener();
    }
    public virtual void Init()
    {
    }
    public virtual void AddUIEventListener()
    {
    }
    public virtual void RemoveUIEventListener()
    {
    }
    public virtual void Show()
    {
        this.rootObj.SetActive(true);
    }
    public virtual void Update()
    {
    }
    public virtual void Hide()
    {
        this.rootObj.SetActive(false);
    }
    public virtual void Destroy()
    {
        RemoveUIEventListener();
        GameObject.Destroy(this.rootObj);
    }
}

飞机有四个不同的组件(body,gun,missile,trail),它们的组装界面统一使用FactoryPage来实现界面逻辑功能。
笔者这里在每次切换不同组件的时候,都会重新调用构造函数,来设置unitType。同时还会Hide()一次界面,再重新Show()一下。

从上面代码中可以看出:笔者事件侦听和移除是分别放到AddUIEventListener和RemoveUIEventListener中的。而这两个方法的调用,是通过父类的构造函数和Destroy()方法。
而笔者这里切换组件,是通过重新调用构造函数的方式,那么就没有移除之前的事件委托,反而会导致同一个事件ID会串联多个委托。

笔者这边的情况流程

假设,第一次打开body界面,unitType被设置为body,事件ID为OnUpgradeUnit的事件串联的委托数为1
第二次打开missile界面,unitType被设置为missile,事件ID为OnUpgradeUnit的事件串联的委托数为2
第三次打开gun界面,unitType被设置为gun,事件ID为OnUpgradeUnit的事件串联的委托数为3
此时,我们无论断点还是debug,都可以获得unitType为gun。这也是符合常规认识的一个结果。

这个时候点击升级按钮,触发OnUpgradeUnit事件。那么它会先调用自己的第一个委托,于是获得了变量unitType为body的错误信息。而无论你如何断点,都找不到是什么时候改变了这个变量值为body的信息。

解决方法

由于笔者切换组件会先Hide()再Show()。故可以把事件侦听放到Show()当中,事件移除放到Hide()方法中。
至此,可以保证事件ID为OnUpgradeUnit的事件,在FactoryPage界面有且最多只有一个委托引用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iningwei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值