分享

【Unity&C#】委托学习经验

 kiki的号 2017-03-21

一、前言:

    众所周知委托和事件是C#的一个重要知识,但是并不是特别好理解的点,在真正接触到商业项目开发前我也是一知半解(当然现在也是一知半解),并且去面试的几家公司,几乎都会问什么是委托,委托有什么用,下面把我这一段时间学习到的分享给大家,希望可以帮助大家,若哪里说得不对请及时喷我。

二、小场景:

    简单说一下大家都应该知道了的知识,我们在写方法在类与类传递数据的时候,可以传递各种各样参数,整型,字符串,各种各样的,那么委托就是让我们可以传递方法,类似函数的指针,那么究竟是什么意思呢,有什么作用呢,我们来举个小例子(百度委托的话大部分都举中国话外国话的例子,我们就在Unity里举一个吧...):

1).我们搭一个最最最简单的场景,创建我们的主角,肖文和孙宇然后分别给他们挂上脚本,如图:


  

                           (你们才不要想什么红蓝CP的我根本不懂!)


2).我们假设肖文和孙宇都可以实现一个功能,什么功能呢(林健:生孩子吧),好的,我们假设肖文和孙宇都可以生孩子,并且比较简单,点击就可以生孩子,点一个生一个,我们把一个球做成Prefab作为孩子,监测一下鼠标事件,鼠标点击到就生一个孩子,这里比较简单我就不截图了,然后呢,这两个孩子肯定是不一样的,所以我们需要区分他们。比如名字不一样啊,哭声不一样啊,大小不一样啊之类的,简单代码如下:



3).OK 运行后我们点击肖文和孙宇可以看到生成的孩子,他们的名字 、哭声和缩放比都不一样,我们简单的实现了我们的功能。现在加入策划提出了新的需求,当你点击去揍(click)他们的孩子的时候,肖文和孙宇会有不同的反应,比如你揍了肖文的孩子肖文就气得骂你,你揍了孙宇的孩子的话孙宇会哭....

我们可以发现这样的问题,你揍孩子这件事是孩子捕捉到的,但是肖文和孙宇的反应是他们自身的逻辑事件,我们应该怎么来把他们联系起来解决这个问题呢?最简单的方法就是委托,我们在肖文和孙宇两个类里封装好他们面对孩子被揍时会发生的方法,然后把这个方法传递给他们的孩子,当孩子被揍的时候,就会启动这个方法,来看代码:



4).这样需求就实现了,当我点击肖文生的孩子时,肖文会生气的说你是个流氓,当我点击孙宇的孩子的时候,孙宇会难过的哭。

来看一下代码,我在Children里增加了一名成员,ActionBeInjured,Action是系统写好的一个委托泛型,比较方便好用我就直接拿过来用了,当然跟你自己写委托本质上没什么区别,意思就是当孩子被揍的时候,我会执行什么方法。而具体执行的方法是写在孙宇和肖文两个类里面的,在初始化的时候,把方法作为参数传递过去就可以了。

(林健:停停停,你干嘛这么费劲这样做呢,直接把被揍时肖文和孙宇要喊的字符串作为参数传递过去就好了呀,何必要写什么委托呢)OK,林健同学灰常机智的发现了一个问题,我们的确可以这样做,把字符串传递过去,就像传递哭声一样,一样可以实现。

但是假如现在需求变成了当孙宇的孩子被揍的时候,孙宇不只哭,还会难过的的转圈,会难过的瘦一圈,这种事情,我们用传递字符串就不能解决了吧,因为难过的转圈和瘦一圈这种事情和肖文的生气的说你是个流氓没有任何逻辑上的联系,不是修改一个参数就可以解决的。但是我们如果使用委托,只需要在孙宇类里改写一下Sad方法就可以了,如下:



我们再去点击孙宇孩子的时候,就会发现孙宇已经开始难过的转圈和瘦一圈了...是不是灰常的简单!

 

5).如果不这么做的话,我们就需要在孩子类里建一个标示其父亲的枚举值,然后把这个枚举值传递进来,当孩子被揍的时候,去判断这个枚举值来去选择究竟去执行什么方法,并且还要把方法的具体实现写在孩子类里,这种逻辑岂不是太奇怪了???明明是肖文和孙宇执行的方法,非要要强行写到孩子类里面去...

或者你在孩子类里建一个GameObject father,然后去调用这个father的方法,但是这样做也有很多问题,第一你去调用的方法究竟是在Sunyu这个类里面还是Xiaowen这个类里面呢,你需要写判断究竟是哪个类。并且当有新的需求:比如战术也可以生孩子的时候,你还要重新改写Children类,增加新的判断和新的枚举类型,这样维护起来实在太麻烦了,牵一发而动全身,

你的老板(好吧你的老板并不懂代码)..你的同事看到这种代码肯定会疯掉的。


6)而如果我们继续使用这种委托来解决的话,开发战术这个类的时候,只需要在战术类里面写好要回调的函数(即战术的孩子被揍时战术会做什么事),然后作为参数传递进去就可以了。而孩子类我们不需要做任何的修改。这样看起来委托是不是相当的coooooooooooool..

  

三、总结:

              下面是我个人的一些心得体会:

              在比较大的项目开发过程中,模块都是独立开发的,并且有很好的通用性和封闭性。没有哪个程序员希望看到的是写个新模块要用到其他的模块时,还要去重新改写原来别人写的模块。并且一个模块的一切逻辑,肯定都要写在这个模块中的,这样如果出现了Bug和新的需求的时候,能够快速的定位到要去修改和添加的地方,而不是这儿改改哪里修修,最后把整个系统改炸了...

              在一个系统(或者游戏)中,会有很多风马牛不相及的模块会公用同样的模块,例如AB两个模块在运行的时候都会使用C模块,然后使用C模块时对于AB两个模块产生的影响是完全不相同的,这样就需要回调函数了,产生的影响这个逻辑是写在AB模块的,而什么时候产生影响是由C决定的,这样把逻辑本身的实现和逻辑触发的条件分开,是非常重要的,这也是很多设计模式上所要求的。

              很喜欢一句话,代码是给人看的,不是给机器看的,机器看的只是二进制代码,所以写代码的时候尤其是项目开发的时候,一定要有良好的代码风格,设计好良好的框架,让别人和将来的自己都能看懂,这样才能开开心心的码!

 

 

              PS:语言风格比较扯...希望大家不嫌弃 

              代码比较小看不清楚的话,可以右下角调大比例 

              还比较年轻,理解的比较浅,喷的话别喷的太严重...

              欢迎大家私戳我讨论一切程序上的问题,这样大家才能相互进步嘛(:一本正经的胡说道)


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多