# 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常用协程功能封装的更多相关文章

  1. c#基类 常用数据验证的封装,数字,字符,邮箱的验证

    #region 常用数据验证的封装,数字字符的验证       /// <summary>       /// 常用数据验证的封装,数字字符的验证       /// </summa ...

  2. 游戏编程之Unity常用脚本类的继承关系

    前言学习Unity开发引擎的初学者会接触大量的脚本类,而这些类之间的关系往往容易被忽略.本文对Unity引擎开发中的一些常用类及其关系进行了简单的归纳总结. 博文首发地址:http://tieba.b ...

  3. Unity常用常找(二)

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/51315050 作者:car ...

  4. unity常用小知识点

    感觉自己抑郁变得更严重了,超级敏感,经常想崩溃大哭,睡眠超差,实在不想药物治疗,多看看书,多约约朋友,多出去走走. 来几句鸡汤吧,人一定要活得明白一点,任何关系都不要不清不楚,说不定最后受伤的就是自个 ...

  5. 关于Unity中协程、多线程、线程锁、www网络类的使用

    协程 我们要下载一张图片,加载一个资源,这个时候一定不是一下子就加载好的,或者说我们不一定要等它下载好了才进行其他操作,如果那样的话我就就卡在了下载图片那个地方,傻住了.我们希望我们只要一启动加载的命 ...

  6. Unity(四)IocContainer 封装类库

    首先要在项目中安装Unity,通过NuGet搜索Unity. 1.定义接口 IDependencyResolver using System; using System.Collections.Gen ...

  7. [Unity菜鸟] 协程Coroutine

    1.协程,即协作式程序,其思想是,一系列互相依赖的协程间依次使用CPU,每次只有一个协程工作,而其他协程处于休眠状态. unity中StartCoroutine()就是协程,协程实际上是在一个线程中, ...

  8. VSPackge插件系列:常用IDE功能的封装

    继上一篇VSPackge插件系列简单介绍如何正确的获取DTE之后,就一直没发VSPackge插件系列的文章了,最近同事也想了解如何在代码中与VS交互,特发一篇文章示例一些简单功能是如何调用,也以备以后 ...

  9. MYSQL常用操作函数的封装

    1.mysql常用函数封装文件:mysql.func.php <?php /** * 连接MYSQL函数 * @param string $host * @param string $usern ...

随机推荐

  1. JAVA知识点总结(五)(常用类)

    第十八章:常用类 一.main方法解读: public static void main(String[] args) //当点击运行时,JVM会自动调用main方法 //public: 被JVM调用 ...

  2. Spring MVC 梳理 - handlerMapping和handlerAdapter分析

    参考图片 综上所述我们来猜测一下spring mvc 中根据URL找到处理器Controller中相应方法的流程 ①:获取Request的URL ②:从UrlLookup这个map中找到相应的requ ...

  3. CSS3 box-shadow阴影

    box-shadow: color x-offset v-offset blur spred color: 阴影的颜色 x-offset: 阴影水平距离; 0: 左右阴影平分:正值:阴影在对象的右侧: ...

  4. flexible.js分析--JavaScript

    //立即执行函数 (function flexible(window, document) { // 获取的html 的根元素 var docEl = document.documentElement ...

  5. UVA12983 The Battle of Chibi

    第一眼能看出来是个dp O($n^3$) 暴力应该很好想 dp[i][j] = $\sum_{k=1}^i [a[k] < a[i]] *dp[k][j-1]$ 发现dp[i][j] 为前面小于 ...

  6. IDEA 学习笔记之 Web项目开发

    Web项目开发: 添加新模块: 起名: 添加jars: 添加Tomcat/local: 添加项目:  启动Tomcat: 看到web页面: 修改页面: 重新部署页面:

  7. Eclipse导入别人项目爆红叉

    1.导入项目之前,请确认工作空间编码已设置为utf-8:window->Preferences->General->Wrokspace->Text file encoding- ...

  8. Egret资源跨域问题

    在服务器上配置了允许跨域还不够,还需要在引擎配置允许跨域,不然texture无法在webgl上下文中渲染 会报一个类似于The cross-origin image at 的错误, 只需要在egret ...

  9. Java8新特性时间日期库DateTime API及示例

    Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和SimpleDateFormat等API ...

  10. [插件化开发] 1. 初识OSGI

    初识 OSGI 背景 当前product是以solution的方式进行售卖,但是随着公司业务规模的快速夸张,随之而来的是新客户的产品开发,老客户的产品维护,升级以及修改bug,团队的效能明显下降,为了 ...