# 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. ReactNative实现GridView

    ReactNative内置了ListView组件但是没有类似GridView这样的组件.利用一些已经有的属性是可以实现GridView的,利用ContentContainerStyle的属性然后配合样 ...

  2. 完整的Android MVP开发之旅

    开发背景 最近是在做一个与健身相关的APP,里面有训练器模块基本功能是按照特点动作的演示和描述来引导用户完成训练.在第一个版本时由于没接触过些类项目与功能花了几周的时间大概1500行代码才完成这个功能 ...

  3. .net core 3.0 Signalr - 02 使用强类型的Hub

    ## 强类型的优缺点 - 优点 强类型的Hub可以避免魔法函数名,相比弱类型更容易维护和发现问题,直接上代码 - 缺点 特么的得多些好几行代码 ## 代码 ### 接口定义 ``` C# /// // ...

  4. Django之使用haystack+whoosh实现搜索功能

    为了实现项目中的搜索功能,我们使用的是全文检索框架haystack+搜索引擎whoosh+中文分词包jieba 安装和配置 安装所需包 pip install django-haystack pip ...

  5. 虚拟现实研究经典问卷Presence Questionnaire (PQ) 详细介绍

    虚拟现实(VR)是一种沉浸式体验,它的作用就是将用户完全包裹在一个人为构建出的(数字)虚拟世界中,让用户在这个新环境中得到不一样的体验,或完成一些现实中不能完成的任务.所以让体验者相信“我身处此中”非 ...

  6. 文件操作——RandomAccessFile

      文件操作——RandomAccessFile 构建RandomAccessFileJava提供了一个可以对文件随机访问的操作,访问包括读和写操作.该类名为RandomAccessFile.该类的读 ...

  7. JVM(四)类加载机制

    1.静态绑定和动态绑定 静态绑定:即前期绑定,在程序执行前方法已经被绑定,此时由编译器或者其他连接程序实现,针对Java,可以理解为编译期的绑定,java中只有final.static.private ...

  8. Ubuntu server 安装及jdk+mysql安装教程

    Ubuntu server 安装教程 1.查找及下载Ubuntu镜像文件 可以在以下页面下载想要的版本,我这里选择19.04 server版的iso镜像文件: http://mirrors.163.c ...

  9. 安装web3失败问题

    ① 首先可以先通过 npm cache verify 清理下缓存,在进行安装 ② 如果还是安装失败可以尝试 ---   npm install web3@^0.20.0  或者 npm install ...

  10. @DateTimeFormat注解

    @DateTimeFormat在spring-context依赖下,所在包如下 当form表单中出现时间字段需要跟pojo对象中的成员变量进行数据绑定时,springmvc框架中的时间数据无法自动绑定 ...