C#神器 委托 + Unity神器 协程
作为源生的C#程序员,可能已经非常了解委托(delegate)、行动(Action)以及C#的事件了,不过作为一个半道转C#的程序员而言,这些东西可能还是有些陌生的,虽然委托并非是C#独创,亦非是首创,C++的函数指针就完全类似于委托的功能,但很多东西没有委托的话实现起来还是很伤脑筋的。
本文主要介绍委托与unity协程之间组合开发的便利,实质上也是对平常的学习和工作中学到的东西做个记录。
一、委托
定义委托:public delegate void MyDelegate(int
_num);
//定义一个委托MyDelegate,如同定义一个类一样,此时的委托没有经过实例化是无法使用的,而他的实例化必须接收一个返回值和参数都与他等同的函数,此处的委托MyDelegate只能接收返回值为void,参数为一个int的函数
实例化委托:MyDelegate _MyDelegate=new MyDelegate(TestMod);
//以TestMod函数实例化一个MyDelegate类型的委托_MyDelegate,此处TestMod函数的定义就应如下:
public void TestMod(int
_num);
//之后调用_MyDelegate(100)时就完全等同于调用TestMod(100)
二、协程
定义协程:public IEnumerator MyCoroutine(){
};
//定义一个协程MyCoroutine,不同于定义类或委托,此时的协程是可以直接使用的,Unity的每一个执行周期里都会包含属于协程的那一部分,只要是场景中属于激活状态的物体(active为true),如同update那般,Unity在渲染的每一帧都会去查找该物体上是否存在协程部分的代码,若存在则加入该物体协程的执行周期,协程部分的代码会如同update那样被Unity每帧执行,当然不同于update的是,大部分协程内部不存在延时的话,一次执行之后便会跳出了,而且既然是处于Unity规定的生命周期里的模块,协程如同update一样当他们所在的物体属于未激活的话(active为false),该物体上所有脚本中包含的协程代码都是不会被执行的。
使用协程:StartCoroutine(MyCoroutine());
//使用StartCoroutine函数将协程MyCoroutine加入此脚本所在物体的协程执行周期内,如果在渲染的下一帧此物体依旧是处于激活状态的话,那么协程MyCoroutine中的代码便会得到Unity执行。
三、委托+协程
其实网上关于这个的例子很多,我在这里只是做个比较系统的归纳。
还记得Unity的Invoke("test",2)吗(延时2秒后执行函数test)?不得不说这是个很大的坑,test函数不能赋予参数不说,还必须得是在当前类里面的方法,而对于延时执行等控制时间轴的操作,这在任何一个项目中肯定都是不可少的,索性有协程,我们完全可以替换掉Invoke的作用。
我们可以自己写一个延时控制器:
/// <summary>
/// 延时执行
/// </summary>
/// <param name="action">执行的委托</param>
/// <param name="delaySeconds">延时等待的秒数</param>
public IEnumerator DelayToInvokeDo(Action action, float delaySeconds)
{
yield return new WaitForSeconds(delaySeconds);
action();
}
/// <summary>
/// 使用例子
/// </summary>
StartCoroutine(DelayToInvokeDo(delegate() {
task.SetActive(true);
task.transform.position = Vector3.zero;
task.transform.rotation = Quaternion.Euler(Vector3.zero);
task.doSomethings();
},1.5f));
我们可以看到这里的例子是在1.5秒之后执行一个匿名委托,该委托的内容是将游戏物体task激活,并设置其位置与旋转属性,然后可以做更多的事情。
不过好像有些缺陷,task这个变量是哪里来的?Unity能否识别?事实上无论task是本类的全局静态变量还是普通单例变量,甚至只是一个与此部分协程代码处在同一域中的局部变量,加入到协程执行周期以后,短期内他是不会被释放的,也就不用担心Unity在后续执行到task的SetActive的时候会报空引用的错了。
只不过我们确实可以将之完善一下,或许我想更好的控制task。
/// <summary>
/// 延时执行
/// </summary>
/// <param name="action">执行的委托</param>
/// <param name="obj">委托的参数</param>
/// <param name="delaySeconds">延时等待的秒数</param>
public IEnumerator DelayToInvokeDo(Action<GameObject> action, GameObject obj,float delaySeconds)
{
yield return new WaitForSeconds(delaySeconds);
action(obj);
}
/// <summary>
/// 使用例子
/// </summary>
StartCoroutine(DelayToInvokeDo(delegate(GameObject task) {
task.SetActive(true);
task.transform.position = Vector3.zero;
task.transform.rotation = Quaternion.Euler(Vector3.zero);
task.doSomethings();
},GameObject.Find("task1"),1.5f));
1.5秒之后执行一个匿名委托,该委托的内容是将游戏物体task激活,并设置其位置与旋转属性,然后可以做更多的事情,这里的task是我们从场景中获取的name为task1的物体,将之作为参数传入了委托中。
后续你可能需要更多的参数,更多的种类,不过那只需要在此基础上扩展就可以了,最后将协程DelayToInvokeDo放在一个全局脚本内,定义一个该脚本的静态变量,那么就可以在项目的任何位置加入这个协程了。
C#神器 委托 + Unity神器 协程的更多相关文章
- [Unity菜鸟] 协程Coroutine
1.协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态. unity中StartCoroutine()就是协程,协程实际上是在一个线程中, ...
- Unity使用协程技术制作倒计时器
先上效果图 图片资源来自http://www.51miz.com/ 1.素材准备 在http://www.51miz.com/搜索png格式的数字图片,用Unity自带的图集制作工具,进行分割.Con ...
- 关于Unity中协程、多线程、线程锁、www网络类的使用
协程 我们要下载一张图片,加载一个资源,这个时候一定不是一下子就加载好的,或者说我们不一定要等它下载好了才进行其他操作,如果那样的话我就就卡在了下载图片那个地方,傻住了.我们希望我们只要一启动加载的命 ...
- Unity在协程(Coroutines)内开启线程(Threading )
孙广东 2017.6.13 http://blog.csdn.NET/u010019717 为什么要在协程中开启线程, 因为很多时候我们是需要线程执行完成后回到主线程的.然后主线程在继续执行后续的操 ...
- unity 之协程返回值
yield return null; // 下一帧再执行后续代码yield return 6;//(任意数字) 下一帧再执行后续代码yield break; //直接结束该协程的后续操作yield r ...
- 关于Unity的协程
协程 认识协程 //协程不是多线程:是一段在主程序之外执行的代码 //协程不受生命周影响 //作用:能够口直代码在特定的时间执行. //1,延时操作 //2,等待某代码执行结束之后执行 /* 特点:1 ...
- 【Unity】协程Coroutine及Yield常见用法
最近学习协程Coroutine,参考了别人的文章和视频教程,感觉协程用法还是相当灵活巧妙的,在此简单总结,方便自己以后回顾.Yield关键字的语意可以理解为“暂停”. 首先是yield return的 ...
- Unity在协程内部停止协程自身后代码执行问题
当在协程内部停止自身后,后面的代码块还会继续执行,直到遇到yield语句才会终止. 经测试:停止协程,意味着就是停止yield,所以在停止协程后,yield之后的语句也就不会执行了. 代码如下: us ...
- 发现一个小坑的地方,unity的协程,想要停止,必须以字符串启动
今天想要停止一个协成,发现调用 StopCoroutine(ShowDebug()); 竟然不管用,后来看了文档才知道,原来想要停止协成,必须用字符启动协程 StartCoroutine(" ...
随机推荐
- 指尖大冒险H5小游戏
前些天看了一篇很赞的文章,又因为想学习phaser,所以有了这个案例,在线预览可以点下方链接. 本案例中,核心原理是按文章中所提到的内容制作,整体遵循"大道至简"的原则开发,其实是 ...
- Linux用户管理命令大全
1.添加用户,首先用adduser命令添加一个普通用户,命令如下: $ adduser tommy //添加一个名为tommy的用户 $ passwd tommy //修改密码 Changing pa ...
- 项目管理软件系列-Linux一键安装禅道
linux用一键安装包 简介:本文介绍如何在linux下面使用禅道一键安装包搭建禅道的运行环境. linux一键安装包内置了apache, php, mysql这些应用程序,只需要下载解压缩即可运行禅 ...
- bash的工作特性及其使用方法
bash的工作特性之命令执行状态返回值和命令展开所涉及的内容及其示例演出 !脚本执行与调试1.绝对路径执行,要求文件有执行权限2.以sh命令执行,不要求文件有执行权限3..加空格或source命令执行 ...
- VLAN之间单臂路由通信
实验目的 理解单臂路由的应用场景 掌握路由器子接口的配置方法 掌握子接口封装VLAN的配置方法 理解单臂路由的工作原理 实验原理 单臂路由解决用户需要跨越VLAN实现通信的情况. 原理:通过一台路由器 ...
- 【C#复习总结】匿名类型由来
1 属性 这得先从属性开始说,为什么外部代码访问对象内部的数据用属性而不是直接访问呢,这样岂不是更方便一些,但是事实证明直接访问是不安全的.那么,Anders Hejlsberg(安德斯·海尔斯伯格) ...
- ACM 畅通工程
Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标是使全省任何两个城镇间都可以实现交通 ...
- Java 求n天前的时间或者n月前的时间
时间格式化 public static String DEFAULT_FORMATDATE = "yyyy-MM-dd"; 1.n天前的日期 /** * luyanlong * 默 ...
- webpack 将不同类型的文件输出到不同文件夹
参考:https://stackoverflow.com/questions/33058964/configure-webpack-to-output-images-fonts-in-a-separa ...
- Bootstrap3 概述
注意:HTML5 文档类型 Bootstrap 使用到的某些 HTML 元素和 CSS 属性需要将页面设置为 HTML5 文档类型.在你项目中的每个页面都要参照下面的格式进行设置. <!DOCT ...