ugui的事件回调与观察者模式

unity中UI的触发方式

使用过unity的ugui的基本都知道通过给Button或者其他UI组件绑定需要触发的事件,然后在运行时,对对应的UI进行点击或者进行值的改变时,便会触发所绑定的事件。

触发原理以及对设计模式的思考

这种触发方式很容易让我们联想到回调函数。没错,不管是通过面板上或者代码为UI添加事件,他都是采用了回调的方式对事件进行调用。而这又让我们联想到设计模式中的一种,观察者模式。我们将对这个UI值感兴趣的方法,通过事件的方式添加到他的回调函数中,从而构成观察者(事件)与被观察者(UI)的关系。

理解回调函数 ,在我们编程时,函数或者说方法,其实就是一个代码块,我们通过函数名(代码块所在地址)来调用整个代码块。而回调函数中我们怎么才能知道什么时候需要回调呢?这就是之前讲过的对值的观察。当值发生改变的时候就会进行回调。一般可以在属性的set方法里面进行设置。例如:

// An highlighted block
public class Test
{
   private int value;
   public int Value
   {
       get { return value; }
       set
       {
           if (value != this.value)
           {
               this.value = value;

               //Action?.Invoke();     
               //执行一个委托方法,Action是委托中的一种,这句话的意思是如果委托不为空,则执行。
               //我们给这个值绑定方法的话就给该Action委托添加事件
           }
       }
   }
}

当然这只是我个人的一种理解方式

这种回调的方式在unity中有一个致命缺点

大家可能会遇到这么一个问题。
在unity中在脚本中用AddListener() 给一组UI添加触发事件
如下面代码

void Start()
   {
       Button[] btns = Cube.GetComponentsInChildren<Button>();

       for (int i = 0; i < btns.Length; i++)
       {
           btns[i].onClick.AddListener(delegate
           {
               Onclick(i);
           });
       }
   }

   void Onclick(int i)
   {
       Debug.Log(i);
   }

测试结果,所有的debug都输出的是for循环的最后一个i的值。

我们来分析一下为什么会出现这种情况。

我们首先获取了cube(一个UI物体名字)上所有子物体的button组件,然后通过for循环给所有的button绑定onclick事件。因为这个事件带参,所以我们通过委托的方式调用。按理来说我们点击不同的按钮输出的应该是不同的值。但是事实却并非如此!

仔细想想委托和回调的本质

回到之前的代码块执行指定的语句。没错,回到之前的代码块!也就是说我们绑定完方法之后,i值已经变成了最后一个。我们的方法传进去的值也理所当然就是最后一个!所以在unity中我们不能通过一个批处理让所有的button绑定同一个带可变参数的方法。 当然如果你有,请一定告诉我,让我学习一波,点个赞。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值