unity3d学习(十二)协程的基础讲解

勇哥注:

协程是字面意思,就是协作关系的代码。

用过之后感觉跟C#的async await很像,也就是异步。

但根据一些资料可以知道,对于脚本代码的执行,unity是使用的单线程的。

因此它的这个协程并不是多线程,它究竟是个什么原理,是比较有意思的话题。


image.png

协程的作用:

任何的程序代码和逻辑处理都是按照顺序执行的。

协程就是开启一段和主程序异步执行的逻辑处理。

但是我们的代码并不是同时执行的。

协程会通过我们不同的yield指令把我们的代码穿插在我们的代码的生命周期中。


yield指令都有些什么呢?后面会介绍。


(一)我们先了解开启和关闭协程。

特点是:IEnumberator 开头,并且函数体中有一句yield;


下面是协程方法和普通方法的对比:

IEnumberator PrintNum()

{

  Debug.Log(2);

  Debug.Log(3);

  yield return 0;

}


void PrintNum()

{

  Debug.Log(2);

  Debug.Log(3);

}


当运行到 yield return 0; 这一行时,就会把程序暂时挂起。

当我们满足一个特定的条件时,才会继续执行我们剩下的代码。


调用协程函数是不能这样:

PrintNum();

而是要这样:

StartCoroutine(PrintNum());


(二)关闭协程


StopCoroutine(PrintNum());

StopAllCoroutines();   //关闭全部协程


(三)详细了解yield

IEnumberator PrintNum()

{

  Debug.Log(1);

  yield return 0;

  Debug.Log(2);

}


void Start()

{

  StartCoroutine(PrintNum());

  Debug.Log(3);

}


 这里代码 yield return 0; 作用就是在执行它时把程序挂起,并在这一帧的Update()执行后,再执行我们剩下的代码。

这里的执行顺序会变成:1--3--2

如果上面的协程是个普通函数,执行顺序则是:1--2--3


yield return 0;改成 yield return null;  效果是完全一样的。


其它的yield用法:


(1)WaitForSeconds(1);

  yield return new WaitForSeconds(1);

  执行这句时,程序挂起到指定秒,再执行后面的语句。

  这里指定的秒数是受 Time.timeScale 影响的。

  因此还有一种不受它影响的方式:

  yield return new WaitForSecondsRealtime(1);

  (2) WaitForFixedUpdate();

   yield return new WaitForFixedUpdate();

  执行这句时,程序挂起,等待所有的物理运算完成后再执行后面的语句。

  FixedUpdate()函数就是给我们物理运算的。

 (3)WaitForEndOfFrame();

  执行这句时,程序挂起,等待这一帧所有的代码都运行完(包括Update(),FiexedUpdate()和我们的GUI渲染),再执行后面的代码。



兴几个粟子


(1)按顺序执行轴动作

下面程序用来移动Cube, 沿矩形路径移动。也就是移动了4个点位。

image.png

源码:

运行后点击Cube对象,启动工作协程。

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.VisualScripting;
using UnityEngine;

public class yieldTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void OnMouseDown()
    {
        Debug.Log("click...");
        StartCoroutine(Working());
    }

    IEnumerator Working()
    {
        yield return StartCoroutine("Move1");
        yield return StartCoroutine("Move2");
        yield return StartCoroutine("Move3");
        yield return StartCoroutine("Move4");
    }

    float distance = 0.01f;
    IEnumerator Move1()
    {
        Debug.Log("forward...");
        for (int i = 0; i < 160; i++)
        {
            transform.Translate(Vector3.forward* distance);
            yield return new WaitForSecondsRealtime(2 / 60);
        }
    }

    IEnumerator Move2()
    {
        Debug.Log("right...");
        for (int i = 0; i < 160; i++)
        {
            transform.Translate(Vector3.right * distance);
            yield return new WaitForSecondsRealtime(2 / 60);
        }
    }

    IEnumerator Move3()
    {
        Debug.Log("back...");
        for (int i = 0; i < 160; i++)
        {
            transform.Translate(Vector3.back * distance);
            yield return new WaitForSecondsRealtime(2 / 60);
        }
    }

    IEnumerator Move4()
    {
        Debug.Log("left...");
        for (int i = 0; i < 160; i++)
        {
            transform.Translate(Vector3.left * distance);
            yield return new WaitForSecondsRealtime(2 / 60);
        }
    }

}




其它资料

有一篇B站的视频对协程讲解很到位,各位可以深入了解下。

https://www.bilibili.com/video/BV19Z4y1w7Fa/?spm_id_from=333.337.search-card.all.click&vd_source=96e36d0c4638992f2ce92aad0dbb1882



本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2024-10-25 17:35:04 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864