Unity常用协程功能封装
# 1.前言
unity开发过程中,经常用到一些特定的协程功能,比如延时触发、等待触发、重复操作等。unity自带Invoke以及InvokeRepeating方法,但这些方法均采用反射机制,性能消耗,而且代码混淆时极其容易出错。所以再次对这些功能做以下简单封装。方便后续使用。
# 2.CoroutineJobCenter
CoroutineJobCenter封装了需要的基本方法。
## 2.1 延时触发
延时一定事件触发。
```csharp
public IEnumerator StartJobDelayed(float delayedTime, Action action)
{
yield return new WaitForSeconds(delayedTime);
if (action != null)
{
action();
}
}
public IEnumerator StartJobDelayed<T>(float delayedTime, Action<T> action, T t)
{
yield return new WaitForSeconds(delayedTime);
if (action != null)
{
action(t);
}
}
```
## 2.2 等待触发
等待某一条件返回true时触发,采用unity自带的WaitUntil类。
```csharp
public IEnumerator StartJobUntil(Func<bool> funtion, Action action)
{
yield return new WaitUntil(funtion);
if (action != null)
{
action();
}
}
public IEnumerator StartJobUntil<T>(Func<bool> funtion, Action<T> action, T t)
{
yield return new WaitUntil(funtion);
if (action != null)
{
action(t);
}
}
```
## 2.3 重复触发
### 2.3.1 每隔一帧触发,并规定触发次数。
```csharp
public IEnumerator RepeatJobPerFrame(int count, Action action)
{
for (int i = 0; i < count; i++)
{
yield return null;
if (action != null)
{
action();
}
}
}
public IEnumerator RepeatJobPerFrame<T>(int count, Action<T> action, T t)
{
for (int i = 0; i < count; i++)
{
yield return null;
if (action != null)
{
action(t);
}
}
}
```
### 2.3.2 每隔固定时间触发,并规定触发次数。
```csharp
public IEnumerator RepeatJobPerTimespan(int count, float interval, Action action)
{
yield return new RepeatJobPerTimespan(action, count, interval);
}
```
```csharp
public class RepeatJobPerTimespan : CustomYieldInstruction
{
private Action action;
private int count;
private int repeatCount;
private float timeSpan;
private float startedTime;
public override bool keepWaiting
{
get
{
if (repeatCount >= count)
{
return false;
}
else if(Time.time - startedTime >= timeSpan)
{
startedTime = Time.time;
repeatCount++;
if (action != null)
{
action();
}
}
return true;
}
}
public RepeatJobPerTimespan(Action action, int count, float timeSpan)
{
this.action = action;
this.count = count;
this.timeSpan = timeSpan;
startedTime = Time.time;
repeatCount = 0;
}
}
```
### 2.3.3 规定时间内,间隔触发
**注意:**
由于间隔多长时间 触发的时间间隔并不精确,所以会影响触发次数。比如每隔两秒执行一次,一共执行六秒。则不会执行三次,因为每次等待两秒,根据判断肯定会超过两秒。所以不会有第三次执行。此时可以适当放宽总时间或者减小时间间隔。
```csharp
public IEnumerator RepeatJobInCertainTimeSpan(float timeSpan, float interval, Action action)
{
yield return new RepeatJobInCertainTimespan(action, interval, timeSpan);
}
```
```csharp
public class RepeatJobInCertainTimespan : CustomYieldInstruction
{
private Action action;
private float startTime;
private float lastJobTime;
private float interval;
private float timeSpan;
public override bool keepWaiting
{
get
{
if (Time.time - startTime > timeSpan)
{
return false;
}
else if (Time.time - lastJobTime >= interval)
{
lastJobTime = Time.time;
if (action != null)
{
action();
}
}
return true;
}
}
public RepeatJobInCertainTimespan(Action action, float interval, float timeSpan)
{
this.action = action;
this.interval = interval;
this.timeSpan = timeSpan;
this.startTime = Time.time;
this.lastJobTime = Time.time;
}
}
```
## 2.4 规定的时间内等待触发
这是一个比较常用的方法,比如超时等待。即如果在规定的时间内完成或者超过规定的时间,则进行下一步处理。
```csharp
public IEnumerator WaitUntilInCertainTimespan(float timeSpan, Func<bool> function, Action action)
{
yield return new WaitUntilInCertaiTime(function, timeSpan);
if (action != null)
{
action();
}
}
```
```csharp
public class WaitUntilInCertaiTime : CustomYieldInstruction
{
private Func<bool> function;
private float timeSpan;
private float startTime;
public override bool keepWaiting
{
get
{
if (function() || Time.time - startTime > timeSpan)
{
return false;
}
return true;
}
}
public WaitUntilInCertaiTime(Func<bool> function,float timeSpan)
{
this.function = function;
this.timeSpan = timeSpan;
startTime = Time.time;
}
}
```
# 3.应用
```csharp
using CoroutineJob;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CorountineJobTest : MonoBehaviour
{
public Button button;
private bool flag = false;
private void Start()
{
button.onClick.AddListener(OnStateChange);
//StartCoroutine(CoroutineJobCenter.Instance.StartJobUntil(() => { return flag; }, () =>
//{
// Debug.Log("StartJobUntil");
//}));
//StartCoroutine(CoroutineJobCenter.Instance.RepeatJobPerTimespan(5, 2, () =>
//{
// Debug.Log("RepeatJobPerTimespan");
//}));
//StartCoroutine(CoroutineJobCenter.Instance.RepeatJobInCertainTimeSpan(6, 1.8f, () =>
//{
// Debug.Log("RepeatJobInCertainTimeSpan");
//}));
StartCoroutine(CoroutineJobCenter.Instance.WaitUntilInCertainTimespan(6, () => { return flag; }, () =>
{
Debug.Log("RepeatJobInCertainTimeSpan");
}));
}
void OnStateChange()
{
flag = true;
}
}
```
Unity常用协程功能封装的更多相关文章
- c#基类 常用数据验证的封装,数字,字符,邮箱的验证
#region 常用数据验证的封装,数字字符的验证 /// <summary> /// 常用数据验证的封装,数字字符的验证 /// </summa ...
- 游戏编程之Unity常用脚本类的继承关系
前言学习Unity开发引擎的初学者会接触大量的脚本类,而这些类之间的关系往往容易被忽略.本文对Unity引擎开发中的一些常用类及其关系进行了简单的归纳总结. 博文首发地址:http://tieba.b ...
- Unity常用常找(二)
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/51315050 作者:car ...
- unity常用小知识点
感觉自己抑郁变得更严重了,超级敏感,经常想崩溃大哭,睡眠超差,实在不想药物治疗,多看看书,多约约朋友,多出去走走. 来几句鸡汤吧,人一定要活得明白一点,任何关系都不要不清不楚,说不定最后受伤的就是自个 ...
- 关于Unity中协程、多线程、线程锁、www网络类的使用
协程 我们要下载一张图片,加载一个资源,这个时候一定不是一下子就加载好的,或者说我们不一定要等它下载好了才进行其他操作,如果那样的话我就就卡在了下载图片那个地方,傻住了.我们希望我们只要一启动加载的命 ...
- Unity(四)IocContainer 封装类库
首先要在项目中安装Unity,通过NuGet搜索Unity. 1.定义接口 IDependencyResolver using System; using System.Collections.Gen ...
- [Unity菜鸟] 协程Coroutine
1.协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态. unity中StartCoroutine()就是协程,协程实际上是在一个线程中, ...
- VSPackge插件系列:常用IDE功能的封装
继上一篇VSPackge插件系列简单介绍如何正确的获取DTE之后,就一直没发VSPackge插件系列的文章了,最近同事也想了解如何在代码中与VS交互,特发一篇文章示例一些简单功能是如何调用,也以备以后 ...
- MYSQL常用操作函数的封装
1.mysql常用函数封装文件:mysql.func.php <?php /** * 连接MYSQL函数 * @param string $host * @param string $usern ...
随机推荐
- Emacs 入门(https://www.zybuluo.com/eqyun/note/40788)
下载地址 基本操作(C=Ctrl, M=Alt) C-f 向右移动一个字符 C-b 向左移动一个字符 C-n 移动到下一行 C-p 移动到上一行 M-f 向右移动一个词[对中文是移动到下一个标点符号] ...
- 《图解HTTP》读后记
看了一遍又一遍…………不如记一下 用做笔记的方式来看,发现了好多之前没发现的知识点.....感觉前几次看了跟没看一样... 1.1HTTP通常被译为超文本传输协议,但这种译法并不严谨.严谨的译名应该为 ...
- scrapy爬取迅雷电影天堂最新电影ed2k
前言 几天没用scrapy爬网站了,正好最近在刷电影,就想着把自己常用的一个电影分享网站给爬取下来保存到本地mongodb中 项目开始 第一步仍然是创建scrapy项目与spider文件 切换到工作目 ...
- Spring 梳理-运行时动态注入bean
动态注入的方法 使用占位符 使用Spring表达式
- Centos 6下使用cmake编译安装MariaDB
写在前面 最近在学习Maria DB,为了方便查阅,又为了将所学的知识重新的梳理,特作此随笔一篇,希望过后阅读时能有所感,也希望对大家能够有所帮助. 安装前的准备 大家都知道,在Linux上安装软件一 ...
- awk 命令使用
awk命令就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理.例如: awk -F '/' '{print $NF}' tmp/file.txt 该命令用于读取file. ...
- if [ $# -ne 1 ] 作用
在shell脚本中经常会使用if [ $# -ne 1 ];then...这类脚本 ];then 这段命令是用于判断参数的个数是否为1,不是则进行then的逻辑处理,其中$#表示参数个数,-ne是不等 ...
- 跟文档学习next.js
前言:Next.js 是一个轻量级的 React 服务端渲染应用框架. Next.js中文点击这里 Next.js中文站Github点击这里 新建文件夹安装它: npm install --save ...
- Docker实战笔记命令篇
拉取一个镜像 docker pull ubuntu:14.04 查看系统中的镜像 docker images 运行镜像并进入 docker run -it ubuntu:14.04 查看运行的容器 d ...
- Kafka 学习笔记之 Producer/Consumer (Scala)
既然Kafka使用Scala写的,最近也在慢慢学习Scala的语法,虽然还比较生疏,但是还是想尝试下用Scala实现Producer和Consumer,并且用HashPartitioner实现消息根据 ...