Jtro的技术分享:unity中使用事件与委托加单例

举报
LittleU 发表于 2022/01/20 14:38:53 2022/01/20
【摘要】 在unity开发中,如果你频繁的使用bool值判断,代码臃肿繁琐,请立即停止它!有的时候用一些简单的办法就可以得到你以前几百行代码的效果。鄙人尽量用简单的例子来说明问题,让有编程功底的人简明扼要的明白。那么,什么情况下要用到事件和委托呢?请看下面的场景:一辆公交车上,乘客A要在第二站下车,乘客B要在第三站下车,乘客到哪下车,公交车不关心。有的同学会用if判断语句:```if (到了第二站){...

在unity开发中,如果你频繁的使用bool值判断,代码臃肿繁琐,请立即停止它!有的时候用一些简单的办法就可以得到你以前几百行代码的效果。

鄙人尽量用简单的例子来说明问题,让有编程功底的人简明扼要的明白。

那么,什么情况下要用到事件和委托呢?

请看下面的场景:一辆公交车上,乘客A要在第二站下车,乘客B要在第三站下车,乘客到哪下车,公交车不关心。

有的同学会用if判断语句:

```
if (到了第二站)
{
乘客A下车;
}
if (到了第三站)
{
乘客B下车;
}
```

...........

这样的逻辑是没有任何问题的,但是需求是:车上的人下车地点都不一样,上面的代码就会无限制的扩充。严重破坏代码的封装性。显然这不是我们希望的。

真确的方法应该是:公交车不管有多少人,只发出到站的信息,乘客到了站台,自己下车就好了。

创建一个Bus脚本,编辑如下:

```
//    脚本功能:
//此脚本挂载在:    上
//    初创日期:
//        作者:张曙光
//  第一次修改:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class _Bus : MonoBehaviour {
/// 公交车到站的委托
public delegate void StationEventHandler (int num);//这是一个无返回值有参数的委托
/// 公交车到站的事件
public event  StationEventHandler onStation;//可以加减方法体
int num = 0;//当前的站台号
void Awake ()
{
this.onStation += GetOFF;
}
// Use this for initialization
void Start () {
}//End of Start
// Update is called once per frame
void Update () {
//按下A键就表示到下一站
if (Input .GetKeyDown (KeyCode.A ))
{
num++;
if(num <10)
{
Station (num);//调用方法,传参数
}
}
}//End of Update
public void Station (int num)
{
Debug.Log (num +" 号站台到了");
//调用到站事件,传入站号作为参数
if(onStation != null)
{
onStation (num);
}
}
void GetOFF ( int num )
{
if (num == 2)
{
Debug.Log ("2号乘客下车");
this.onStation -= GetOFF;
}
}
}
```
创建PassengerA脚本,编辑如下:
```
//    脚本功能:
//此脚本挂载在:    上
//    初创日期:
//        作者:张曙光
//  第一次修改:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PassengerA : MonoBehaviour {
public _Bus bus;//声明带有委托的脚本
void Awake ()
{
bus.onStation += Getoff;//这样加方法也是可以的
//bus.onStation += new _Bus.StationEventHandler(Getoff);
}
void Getoff (int num)
{
if (num == 2)
{
Debug.Log ("乘客A在2号站台下车");
//下车之后取消监听公交车到站事件
bus.onStation -= Getoff;
}
}
}
```
创建PassengerB脚本,编辑如下:
```
//    脚本功能:
//此脚本挂载在:    上
//    初创日期:
//        作者:张曙光
//  第一次修改:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PassengerB : MonoBehaviour {
public _Bus bus;//声明带有委托的脚本
void Awake ()
{
bus.onStation += new _Bus.StationEventHandler (Getoff);
}
void Getoff (int num)
{
if (num == 3)
{
Debug.Log ("乘客B在3号站台下车");
//下车之后取消监听公交车到站事件
bus.onStation -= Getoff;
}
}
}
```

在unity中创建3个空对象并命名为:bus,PassengerA,PassengerB,然后将3个脚本分别挂载在上面。运行结果如下图:

e6e6a39ee1a9c9a687124b49987c5b48.png

运行结果

单例:单例就是单个的意思,保证在游戏运行的时候不会有第二个自己存在,一般的解释就是:保证一个类只有一个实例,并提供访问它的全局访问点。一般的,在游戏中UI 用到的最多,当然,小怪也用的比较多。

实现的方式:

```
//    脚本功能:单利
//此脚本挂载在:    上
//    初创日期:
//        作者:张曙光
//  第一次修改:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Single : MonoBehaviour {
public int num = 10;
//单利开始
public static Single instance;
public void Awake ()
{
if (instance == null)
{
instance = this;
}
}
public string showmsg ()
{
return "我是单例";
}
}
```

访问单例:

```
//    脚本功能:
//此脚本挂载在:    上
//    初创日期:
//        作者:张曙光
//  第一次修改:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class visitSigle : MonoBehaviour {
// Use this for initialization
void Start () {
int n = Single.instance.num;
string str = Single.instance.showmsg ();
Debug.Log ("n: "+n +" sting: "+str);
}//End of Start
// Update is called once per frame
void Update () {
}//End of Update
}
```

新建一个空物体,两个脚本都挂上,运行:

e6e6a39ee1a9c9a687124b49987c5b48.png

单例运行结果

优点:不需要重构,直接编码,其他类或者脚本直接使用

缺点:需要把实现单例的类手动绑定到游戏对象上才可以使用

OK,这两个简单的技能学到了以后会比你以前只用bool值判断的的编码轻松不少吧。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。