您的位置:首页 > 移动开发 > Unity3D

实现unity的协同(Coroutine)

2014-01-11 09:24 387 查看
要用c#实现unity的协同,现需要了解c# 的yield用法.

为了简明起见,先上一个简化版本,只实现不带停止功能部分(即没StartCoroutine("xxx")和StopCoroutine("xxx"函数))。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace create_coroutine
{
/// <summary>
/// 同Unity一致
/// </summary>
public class WaitForSeconds
{
public float Elapse;//累加时间
public float Time;//指定时间
public WaitForSeconds(float t)
{
Time = t;
}
}

/// <summary>
/// 协同类
/// </summary>
class Corotine
{
static List<IEnumerator> Corotines = new List<IEnumerator>();
static List<IEnumerator> TmpLst = new List<IEnumerator>();

/// <summary>
/// 开始协同程序
/// </summary>
/// <param name="c"></param>
public static void Start(IEnumerator c)
{
Corotines.Add(c);
}

/// <summary>
/// 主线程调用函数
/// </summary>
/// <param name="delta">两帧之间的时间间隔.单位:秒</param>
public static void MainThread_Update(float delta)
{
TmpLst.Clear();

foreach (IEnumerator c in Corotines)
{
if (c.Current == null
|| (c.Current is int && ((int)c.Current == 0))) //判断是否等待一帧,和yield return break;(后者也会返回null,但是MoveNext()的结果是false.)
{
bool r = c.MoveNext();
if(!r)
TmpLst.Add(c);  //注意:Corotines链表中的对象不能在foreach循环内删除
}
else if (c.Current.GetType() == typeof(WaitForSeconds)) //判断等待一段时间
{
WaitForSeconds wfs = c.Current as WaitForSeconds;
wfs.Elapse += delta;  //逐帧累加时间
if (wfs.Elapse >= wfs.Time) //累加时间大于指定等待时间则跳过
{
bool r = c.MoveNext();
if (!r)
TmpLst.Add(c);
}
}
//...在此处可以加入其他判断 WaitForEndOfFrame 或者 WaitForFixedUpdate

}

foreach (IEnumerator c in TmpLst)
{
Corotines.Remove(c);
}
}
}

/// <summary>
/// 测试用例
/// </summary>
class Program
{
static IEnumerator GetI()
{
yield return new WaitForSeconds(1F);
Console.Write("a");
yield return 0;
Console.Write("b");
yield return null;
Console.Write("c");
}

static void Main(string[] args)
{
float delta = 0.005F;
Corotine.Start(GetI());
while (true)
{
DateTime timeStart = DateTime.Now;
Corotine.MainThread_Update(delta);
System.Threading.Thread.Sleep(5);
delta = (float)(DateTime.Now - timeStart).TotalSeconds;
}
}
}
}


后记:

unity用久了之后自然对其中的协同函数(coroutine)有一种依赖。

亦因为最近服务器程序的需求,所以手动实现一个协同机制来简化代码很有必要。

使用协同后对代码的好处可以参考c兄的:

点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息