Unity协程学习心得

news2024/11/23 23:44:50

前言

个人总结的一些Unity协程学习心得,如有不对请在评论区指出一起学习!感谢。

在Unity编程中谈到异步逻辑,可以考虑使用协程来实现。协程(Coroutine)在Unity中的主要作用就是把一个任务暂停(挂起),并在下一帧(或之后的某一时间点)继续。常见案例有网络请求、临时计时器、资源加载、打字机特效等。需要注意的是,协程不是线程,协程是在主线程中执行的。使用协程可以不用考虑同步和锁的问题。

1、C#迭代器

官方文档:遍历集合 - C# | Microsoft Learn

在了解并使用协程之前,我们可以先扩展一下关于C#迭代器的知识,方便我们理解什么是yield

迭代器方法或 get 访问器可对集合执行自定义迭代。 迭代器方法使用 yield return 语句返回元素,每次返回一个。 到达 yield return 语句时,会记住当前在代码中的位置。 下次调用迭代器函数时,将从该位置重新开始执行。迭代器方法或 get 访问器的返回类型可以是 IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>。

在C#中,yield可以粗浅的理解为“产出”。用于实现迭代器,逐步产出序列中的元素

案例:写一个返回数字的迭代器方法

void Start()
{
    var numbers = GetNumbers();
    while (numbers.MoveNext())
    {
        Debug.Log($"t_Coroutine {numbers.Current}");
    }
}

IEnumerator GetNumbers()
{
    yield return 0;
    yield return 1;
    yield return 200;
}

 输出:

但是在Unity中,我们只用到了IEnumerator来创建协程方法。因此,我着重介绍一下IEnumerator接口。

1.1 IEnumerator

public interface IEnumerator
{
    object Current
    {
        get;
    }

    bool MoveNext();

    void Reset();
}

可以看到其实迭代器内部很简单。

Current是当前迭代器指向的对象;MoveNext()是移动指针指向下一个对象,如果是最后一个对象则返回false;Reset()是重置为最初状态。

2、协程基本语法

2.1 写一个简单的协程

协程开始时,会顺序执行yield return null;之前的代码,遇到yield return 会被挂起(暂停),等待指定时间后,从被挂起的地方继续往下执行。

using System.Collections;
using UnityEngine;

public class CoroutineExample : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(MyCoroutine());
    }

    IEnumerator MyCoroutine()
    {
        // 开启协程就会执行的逻辑
        Debug.Log("t_Coroutine Start Coroutine");
        yield return null;  //在这里被暂停,暂停1帧
        //挂起并恢复之后的逻辑
        Debug.Log("t_Coroutine Wait One Frame After");
        yield return new WaitForSeconds(2); //在这里被暂停,暂停2秒
        Debug.Log("t_Coroutine Wait Two Seconds After");
        //协程结束
    }
}

输出:

 

2.2 yield return的不同用法

2.2.1 yield return null 与 yield return 1

在Unity协程中,yield return null; 和 yield return 1; 实际上是等效的,二者都会暂停协程的执行并在下一帧继续执行。即等待一帧

之所以等效,是因为yield return会返回一个值给Unity的协程调度器,这个值用于决定协程何时继续。null和任意整数(例如1)都会导致协程在下一帧恢复执行。

2.2.2 yield break

立即停止协程

案例:可以看到Break After并没有被打印出来,在此之前协程就停止了

using System.Collections;
using UnityEngine;

public class CoroutineExample : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(MyCoroutineBreak());
    }

    IEnumerator MyCoroutineBreak()
    {
        Debug.Log("t_Coroutine Start MyCoroutineBreak");
        yield return null;  //在这里被暂停,暂停1帧
        Debug.Log("t_Coroutine Wait Two Seconds After");
        yield break;//协程结束
        Debug.Log("t_Coroutine Break After");
    }
}

输出: 

2.2.3 yield return StartCoroutine(OtherCoroutine())

协程是可以嵌套的,可以使用yield return StartCoroutine(OtherCoroutine()),等待OtherCoroutine协程方法执行完毕后,再继续往下执行

案例:

void Start()
{
    Debug.Log("t_Coroutine Start1");
    StartCoroutine(TestCoroutine());
    Debug.Log("t_Coroutine Start2");
}

IEnumerator TestCoroutine()
{
    Debug.Log("t_Coroutine test1");
    yield return StartCoroutine(LoadCoroutine());
    Debug.Log("t_Coroutine test2");
}

IEnumerator LoadCoroutine()
{
    Debug.Log("t_Coroutine load 1");
    yield return null;
    Debug.Log("t_Coroutine load 2");
}

输出:

 

 2.2.4 其他用法

yield return new WaitForEndOfFrame();//等待帧结束

yield return new WaitForSeconds(1f);//等待1秒;

yield return WebRequest();//等待到网络请求结束返回结果的时候;

yield return new WaitUntil()//等待到结果返回为true的时候

yield return new WaitWhile()//等待到结果返回为false的时候

2.3 开启 / 停止协程

2.3.1 直接开启一个协程

无法控制暂停,直接调用协程方法开启

StartCoroutine(MyCoroutine());

2.3.2 用变量控制协程

private Coroutine myCoroutine;
myCoroutine = StartCoroutine(MyCoroutine());//开启协程
StopCoroutine(myCoroutine);//停止协程

2.3.3 用协程方法名控制协程

StartCoroutine("MyCoroutine");//开启协程
StopCoroutine("MyCoroutine");//停止协程

2.3.4 停止所有正在运行的协程

会停止该对象上所有正在运行的协程,慎用!

当一个游戏对象(GameObject)把Active设置为false,即SetActive(false),也会停止该对象上附加的协程。

调用Destroy(GameObject)时,Unity会调用OnDisable(),处理并停止协程。在这一帧结束时,会调用OnDestroy()。

StopAllCoroutines();

3、学习参考博客

官方文档:Unity - Manual: Coroutines

通俗易懂博客(建议先看这个,很好理解):Unity C#中协程/携程Coroutine简单易懂详解-CSDN博客

更进一步理解:Unity StartCoroutine - 简书

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1806531.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动态IP在云计算中的应用与优势(短效IP的作用)

一、云计算概述 云计算是指通过互联网将计算资源和服务提供给用户的一种模式。它具有高灵活性、可扩展性和成本效益等特点&#xff0c;使得企业能够快速响应市场变化&#xff0c;降低IT投入成本。云计算的核心优势在于其资源的动态分配和高效利用。 二、动态IP在云计算中的角…

动态IP基础解析:为什么我们需要它?

在深入探讨互联网世界的运作机制时&#xff0c;IP地址无疑是其核心要素之一。IP地址&#xff0c;作为网络设备的唯一标识&#xff0c;不仅确保了数据的准确传输&#xff0c;更是网络安全和管理的基石。本文将深入解析动态IP的基础知识&#xff0c;并探讨其重要性及在多种场景下…

dos命令---根据端口查找进程

简介 在日常开发中&#xff0c;常常出现端口被占用的情况&#xff0c;导致程序运行报错&#xff0c;这时可以使用此命令查看哪个进程占用了端口 命令 netstat -ano | findstr 11434返回结果&#xff1a;

使用React和GraphQL进行CRUD:完整教程与示例

在本教程中&#xff0c;我们将向您展示如何使用GraphQL和React实现简单的端到端CRUD操作。我们将介绍使用React Hooks读取和修改数据的简单示例。我们还将演示如何使用Apollo Client实现身份验证、错误处理、缓存和乐观UI。 什么是React&#xff1f; React是一个用于构建用户…

OpenCompass 大模型评测作业(lesson 7)

书生浦语大模型实战系列文章目录 书生浦语大模型全链路开源体系发展历程和特点&#xff08;lesson 1&#xff09; 部署 InternLM2-Chat-1.8B&#xff08;lesson 2-1&#xff09; 部署八戒demo InternLM2-Chat-1.8B&#xff08;lesson 2-2&#xff09; 部署InternLM2-Chat-7B 模…

牛客热题:最长公共子串

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;最长公共子串题目链接方法一&am…

MySQL之多表查询—行子查询

一、引言 上篇博客学习了列子查询。 接下来学习子查询中的第三种——行子查询。 行子查询 1、概念 子查询返回的结果是一行&#xff08;当然可以是多列)&#xff0c;这种子查询称为行子查询。 2、常用的操作符 、 <> (不等于) 、IN 、NOT IN 接下来通过一个需求去演示和…

博睿数据应邀出席双态IT用户大会,分享《构建云原生时代的一体化智能可观测性》

5月31日-6月2日&#xff0c;第十二届双态IT用户大会于成都成功举行&#xff0c;此次大会由DCMG和双态IT论坛联合主办&#xff0c;聚焦“信创时代的组织级云原生能力建设”和“组织级云原生运维能力建设”两大会议主题&#xff0c;旨在推动双态IT落地与创新&#xff0c;为企业数…

C语言:双链表

一、什么是双链表&#xff1f; 双链表&#xff0c;顾名思义&#xff0c;是一种每个节点都包含两个链接的链表&#xff1a;一个指向下一个节点&#xff0c;另一个指向前一个节点。这种结构使得双链表在遍历、插入和删除操作上都表现出色。与单链表相比&#xff0c;双链表不仅可以…

C++基础编程100题-008 OpenJudge-1.3-06 甲流疫情死亡率

更多资源请关注纽扣编程微信公众号 http://noi.openjudge.cn/ch0103/06/ 描述 甲流并不可怕&#xff0c;在中国&#xff0c;它的死亡率并不是很高。请根据截止2009年12月22日各省报告的甲流确诊数和死亡数&#xff0c;计算甲流在各省的死亡率。 输入 输入仅一行&#xff…

基于NodeJs 的Vue安装和创建项目

基于NodeJs 的Vue安装和创建项目 一、Node.js的下载与安装 下载地址&#xff1a; https://nodejs.org/en/download/prebuilt-installer 安装完之后&#xff0c;启动 cmd命令行&#xff0c;验证 Node.js 是否安装成功 二、配置npm的全局模块的存放路径以及缓存的路径 注&…

[数据集][图像分类]人种黄种人白人黑人等分类数据集56000张7类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;56000 分类类别数&#xff1a;7 类别名称:[“Black”,“East_Asian”,“Ind…

Meta首席AI科学家Yann LeCun指出生成式AI的不足

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

华为防火墙 1

华为防火墙1 实验拓扑&#xff1a; 实验步骤&#xff1a; 1.完成终端基本IP信息配置 2.配置防火墙&#xff1a; 2.1配置IP地址 sys Enter system view, return user view with CtrlZ. [USG6000V1]undo in e Info: Saving log files… Info: Information center is disabled. […

爬虫——有道云翻译

废话不多说直接上代码 固定文本内容 import timefrom selenium import webdriver from selenium.common.exceptions import NoSuchElementException, TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWai…

debian12安装时分区方案

一、初次尝试 一共设置了4个分区&#xff0c;其中根目录/分区46G&#xff0c;swap分区10G&#xff08;电脑内存为6G&#xff09;&#xff0c;/boot分区200M&#xff0c;/home分区55G。系统安装之后的实际占有情况为&#xff1a; 二、调整后情况 一共设置了4个分区&#xff0c…

[vulnhub]Lin.Security主机Linux提权

Hash Crack(Hash cat) boblinsecurity:~$ cat /etc/passwd $ echo "AzER3pBZh6WZE">hash 检查哈希类型: $ hash-identifier AzER3pBZh6WZE $ hashcat -m 1500 -a 0 hash /usr/share/wordlists/rockyou.txt --force username:insecurity password:AzER3pBZh6WZE…

TransformerFAM:革新深度学习的新型注意力机制

深度学习领域的一项突破性技术——Transformer架构&#xff0c;已经彻底改变了我们处理序列数据的方式。然而&#xff0c;Transformer在处理长序列数据时面临的二次复杂度问题&#xff0c;限制了其在某些应用场景下的潜力。针对这一挑战&#xff0c;研究者们提出了一种名为Tran…

sqlmap直接嗦 dnslog注入 sqllibs第8关

dnslog注入是解决注入的时候没有回显的情况&#xff0c;通过dns外带来进行得到我们想要的数据。 我们是用了dns解析的时候会留下记录&#xff0c;这时候就可以看见我们想要的内容。 这个时候我们还要了解unc路径以及一个函数load_file()以及concat来进行注入。看看我的笔记 unc…

每日5题Day19 - LeetCode 91 - 95

每一步向前都是向自己的梦想更近一步&#xff0c;坚持不懈&#xff0c;勇往直前&#xff01; 第一题&#xff1a;91. 解码方法 - 力扣&#xff08;LeetCode&#xff09; class Solution {public int numDecodings(String s) {int n s.length();//注意我们dp的范围是n1int[] d…