# 1.前言
unity開發過程當中,常常用到一些特定的協程功能,好比延時觸發、等待觸發、重複操做等。unity自帶Invoke以及InvokeRepeating方法,但這些方法均採用反射機制,性能消耗,並且代碼混淆時極其容易出錯。因此再次對這些功能作如下簡單封裝。方便後續使用。
# 2.CoroutineJobCenter
CoroutineJobCenter封裝了須要的基本方法。
## 2.1 延時觸發
延時必定事件觸發。
```csharp
public IEnumerator StartJobDelayed(float delayedTime, Action action)
{
yield return new WaitForSeconds(delayedTime);ide
if (action != null)
{
action();
}
}性能
public IEnumerator StartJobDelayed<T>(float delayedTime, Action<T> action, T t)
{
yield return new WaitForSeconds(delayedTime);this
if (action != null)
{
action(t);
}
}
```
## 2.2 等待觸發
等待某一條件返回true時觸發,採用unity自帶的WaitUntil類。spa
```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 每隔一幀觸發,並規定觸發次數。get
```csharp
public IEnumerator RepeatJobPerFrame(int count, Action action)
{
for (int i = 0; i < count; i++)
{
yield return null;it
if (action != null)
{
action();
}
}
}io
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;
}
}
```