实现unity的协同(Coroutine)

要用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
{
    /// 
    /// 同Unity一致
    /// 
    public class WaitForSeconds
    {
        public float Elapse;//累加时间
        public float Time;//指定时间
        public WaitForSeconds(float t)
        {
            Time = t;
        }
    }

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

        /// 
        /// 开始协同程序
        /// 
        /// 
        public static void Start(IEnumerator c)
        {
            Corotines.Add(c);
        }

        /// 
        /// 主线程调用函数
        /// 
        /// 两帧之间的时间间隔.单位:秒
        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);
            }
        }
    }

    /// 
    /// 测试用例
    /// 
    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兄的:

点击打开链接

你可能感兴趣的:(技术)