协同线程

最早接触coroutine是在02年使用unreal engine时。unreal script通过支持latent function和state代码实现了coroutine的思想。由于unreal script属于私有语言,整个语言设计的针对性比较强,所以虽然很好用,但是在语言的通用性上的没有任何的考虑。03年开始接触lua时,被他的coroutine设计吸引住了。把lua的coroutine用在游戏中可谓再合适不过了,而且使用起来更自由一些。Unity中也支持coroutine,虽然思想上和用法上和unreal engine以及lua的大同小异,实现层面还是有本质的区别的。理解Unity中的coroutine的运作机制对于正确的使用coroutine是有很大帮助的。

Unity coroutine的实现机制

先来说说lua coroutine。在lua中,coroutine是通过一个独立的lua state来实现,这个state中保存了coroutine的运行堆栈。在corotine程序中,可以随时暂停执行,保存调用堆栈,也可以在任意时刻恢复执行。lua的coroutine可以说是真正的coroutine。

与lua不同,Unity所使用的mono,也就是.net虚拟机本身并不支持coroutine,coroutine功能是在语言层通过Iterator Blocks模拟出来的。C#将Iterator Block代码转化为一个IEnumerator class代码,并返回这个IEnumerator,外部可以通过调用这个IEnumerator对象的MoveNext()函数来运行一次coroutine。

模拟Unity coroutine

为了理解unity coroutine,自己用C#实现了一个Coroutine系统。虽然没有Unity的source,自己感觉应该和Unity内部实现方法近似的。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public interface IYYieldInstruction
{
    bool isFinished();
}

public class YCCoroutine : IYYieldInstruction
{
    private YCContext c_;
    public YCCoroutine(YCContext c)
    {
        c_ = c;
    }
    public bool isFinished()
    {
        return c_.isFinished();
    }
}
public class YCWait : IYYieldInstruction
{
    private float seconds_;
    public YCWait(float sec)
    {
        seconds_ = sec;
    }
    public bool isFinished()
    {
        seconds_ -= Time.deltaTime;
        return (seconds_ < 0);
    }
}

public class YCContext
{
    IEnumerator coroutine_;
    IYYieldInstruction curYield_;
    bool isFinished_;
    public YCContext(IEnumerator c)
    {
        coroutine_ = c;
        curYield_ = coroutine_.Current as IYYieldInstruction;
    }
    public void step()
    {
        if(isFinished_)
            return;
        if(curYield_ != null && curYield_.isFinished())
            curYield_ = null;
        if(curYield_ == null)
        {
            if(!coroutine_.MoveNext())
                isFinished_ = true;
            else
                curYield_ = coroutine_.Current as IYYieldInstruction;
        }
    }
    public bool isFinished() { return isFinished_; }
}

public class YCoroutineManager : MonoBehaviour
{
    private List<YCContext> contexts_ = new List<YCContext>();

    public YCCoroutine startCoroutine(IEnumerator c)
    {
        YCContext context = new YCContext(c);
        YCCoroutine cr = new YCCoroutine(context);
        contexts_.Add(context);
        return cr;
    }

    void Update()
    {
        for (int i = 0; i < contexts_.Count; i++)
        {
            YCContext c = contexts_[i];
            c.step();
            if (c.isFinished())
            {
                contexts_.Remove(c);
                i--;
            }
        }
    }

    IEnumerator Start()
    {
        Debug.Log(Time.frameCount);
        yield return startCoroutine(c1());
        Debug.Log(Time.frameCount);
    }
    IEnumerator c1()
    {
        Debug.Log(Time.frameCount);
        yield return startCoroutine(c2());
        Debug.Log(Time.frameCount);
    }
    IEnumerator c2()
    {
        Debug.Log(Time.frameCount);
        yield break;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值