协同程序(Coroutines)
博客专区 > LIndieGS 的博客 > 博客详情
协同程序(Coroutines)
LIndieGS 发表于7个月前
协同程序(Coroutines)
  • 发表于 7个月前
  • 阅读 0
  • 收藏 0
  • 点赞 0
  • 评论 0

标题:腾讯云 新注册用户域名抢购1元起>>>   

原文链接:https://docs.unity3d.com/Manual/Coroutines.html

    当你调用一个函数,它先与返回运行结束。这意味着,任何一个发生在函数里的动作必须发生在一个单独的帧刷新里;函数的调用不能被用来包含一个程序化的动画或一个持续一段时间的一系列事件。例如,考虑这样的情况,不断减少一个物体的初值(不透明度)知道它变得完全不可见。

void Fade() {
    for (float f = 1f; f >= 0; f -= 0.1f) {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
    }
}

    实际上,这个函数不会像你希望那样执行。为了使这个淡出效果可视化,初值必须在连续的几帧内不断减少,去显示不断被渲染的中间值。可是,函数会在一帧刷新内就执行结束,这些中间值就不能显示出来,物体也会立即消失。

    解决方案就是在Update函数里加一些代码,这些代码能使淡出效果逐帧显示。但是,更常用的方法是使用coroutine。

    coroutine就像一个函数,它具有暂停函数执行并把控制权交给Unity的能力,同时,能在下一帧里,让函数从暂停的地方继续执行。在C#中,coroutine是这样声明的:

IEnumerator Fade() {
    for (float f = 1f; f >= 0; f -= 0.1f) {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
        yield return null;
    }
}

    它本质上是一个函数,返回值类型是IEnumerator。它还有一个yield return语句,这是实现coroutine功能的关键,也就是暂停程序,在下一帧继续着个功能。为了能使coroutine运行起来,你需要使用StartCoroutine函数:

void Update() {
    if (Input.GetKeyDown("f")) {
        StartCoroutine("Fade");
    }
}

    你需要注意这个Fade函数中的这循环语句,它是保证在coroutine的生命期里,值的正确性。事实上,任何变量或参数都能准确的保存在yield里。

    一帧画面里,coroutine默认在它yield之后继续执行,但也可以使它延迟一段时间执行。这就要用到WaitForSecond:

IEnumerator Fade() {
    for (float f = 1f; f >= 0; f -= 0.1f) {
        Color c = renderer.material.color;
        c.a = f;
        renderer.material.color = c;
        yield return new WaitForSeconds(.1f);
    }
}

    它被常用于扩散一个效果并持续一段时间,它也是一种有用的优化手段。游戏中许多任务需要被定期执行,最好的方法就是把它们写进Update函数里。可是,一个函数通常在一秒中被调用很多次。当一个任务不需要被如此频繁地反复执行时,你能把它放进coroutine里,使它有规律地执行,而不是在每一帧中都执行。比如在游戏中,当敌人出现在玩家附近是,警报就会响起,代码可以这样写:

function ProximityCheck() {
    for (int i = 0; i < enemies.Length; i++) {
        if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
                return true;
        }
    }
    
    return false;
}

    如果附近有很多敌人,调用这个函数就会对硬件产生巨大的开销。这时,你就可以使用coroutine,让它每秒钟调用十次:

IEnumerator DoCheck() {
    for(;;) {
        ProximityCheck;
        yield return new WaitForSeconds(.1f);
    }
}

    这将大大减少执行检查的数量,而不会对游戏产生任何明显的影响。

共有 人打赏支持
粉丝 0
博文 9
码字总数 6421
×
LIndieGS
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: