unity coroutine calldelay定时器原理 — 在此基础上,进一步扩展自定义协同程序等待机制。
继承 UserTypeWait 即可实现自定义的协同程序等待事件,效果类似于 WaitForSeconds、WWW、LoadLevelAsync 等内置等待方式。注意:Loop 方法是同步写法;如果需要真正的异步执行,在内部用多线程包装即可 — 版本4已实现多线程方案(这也许是多核优化的一个思路)。版本3则是 lambda 写法。
总之,想怎么玩就怎么玩。
版本1:类写法1
using UnityEngine;
using System.Collections;
using System;
public class UserTypeWait
{
public IEnumerator Wait()
{
while (Loop())
{
yield return null;
}
}
public virtual bool Loop()
{
return false;
}
}
public class WaitForTickCount50 : UserTypeWait
{
public override bool Loop()
{
++c;
if (c > 50)
{
return false;
}
return true;
}
int c = 0;
}
public class NewBehaviourScript : MonoBehaviour
{
void Start()
{
StartCoroutine(Run1());
}
IEnumerator Run1()
{
Debug.LogError("1111111");
yield return new WaitForTickCount50().Wait();
Debug.LogError("2222222222");
}
}
版本2:类写法2
using UnityEngine;
using System.Collections;
using System;
public class UserTypeWait:IEnumerator
{
public bool MoveNext()
{
return Loop();
}
public void Reset()
{
}
public object Current
{
get
{
return null;
}
}
public virtual bool Loop()
{
return true;
}
}
public class WaitForTickCount50 : UserTypeWait
{
public override bool Loop()
{
++c;
if (c > 50)
{
return false;
}
return true;
}
int c = 0;
}
public class NewBehaviourScript : MonoBehaviour
{
void Start()
{
StartCoroutine(Run1());
}
IEnumerator Run1()
{
Debug.LogError("1111111");
yield return new WaitForTickCount50();
Debug.LogError("2222222222");
}
}
版本3:lambda 写法
using UnityEngine;
using System.Collections;
using System;
public class UserTypeWait : IEnumerator
{
public bool MoveNext()
{
return Loop();
}
public void Reset()
{
}
public object Current
{
get
{
return null;
}
}
public virtual bool Loop()
{
return false;
}
}
public delegate bool BoolFuncVoid();
public class WaitForLambada : UserTypeWait
{
BoolFuncVoid cb;
public WaitForLambada(BoolFuncVoid cb)
{
this.cb = cb;
}
public override bool Loop()
{
if (cb == null)
{
return false;
}
return cb();
}
int c = 0;
}
public class NewBehaviourScript : MonoBehaviour
{
void Start()
{
StartCoroutine(Run1());
}
IEnumerator Run1()
{
Debug.LogError("1111111");
int c = 0;
yield return new WaitForLambada(() =>
{
c++;
if (c > 50) return false;
return true;
});
Debug.LogError("2222222222");
}
}
版本4:多线程写法
多线程写法在某种程度上实现了真正的异步:逻辑上是同步写法,代码却由独立线程执行,做到了"同步写法、异步执行"。多核优化也因此变得更简单,例如可以进一步添加 WaitForThreadJobGroup 这类并发组等待。
using UnityEngine;
using System.Collections;
using System;
public class UserTypeWait : IEnumerator
{
public bool MoveNext()
{
return Loop();
}
public void Reset()
{
}
public object Current
{
get
{
return null;
}
}
public virtual bool Loop()
{
return false;
}
}
public delegate bool BoolFuncVoid();
public delegate void VoidFuncVoid();
public class WaitForThreadJob : UserTypeWait
{
bool isDone = false;
public override bool Loop()
{
return !isDone;
}
System.Threading.Mutex locker = new System.Threading.Mutex();
public WaitForThreadJob(VoidFuncVoid job)
{
thread = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
{
job();
locker.WaitOne();
isDone = true;
locker.ReleaseMutex();
}));
thread.Start();
}
System.Threading.Thread thread;
}
public class NewBehaviourScript : MonoBehaviour
{
void Start()
{
StartCoroutine(Run1());
}
IEnumerator Run1()
{
Debug.LogError("1111111");
int c = 0;
yield return new WaitForThreadJob(() =>
{
for (int i = 0; i < 3000000; i++)
{
Vector3.Distance(Vector3.zero, Vector3.one);
Vector3.Distance(Vector3.zero, Vector3.one);
Vector3.Distance(Vector3.zero, Vector3.one);
Vector3.Distance(Vector3.zero, Vector3.one);
Vector3.Distance(Vector3.zero, Vector3.one);
Vector3.Distance(Vector3.zero, Vector3.one);
Vector3.Distance(Vector3.zero, Vector3.one);
Vector3.Distance(Vector3.zero, Vector3.one);
}
});
Debug.LogError("2222222222");
}
}
Unity 内置了类似功能的等待类:WaitWhile、WaitUntil、CustomYieldInstruction。