第十八章 协程

news2024/11/26 0:30:53

我们知道脚本都是继承自MonoBehaviour类,而其中的Update方法里面放置了大部分的游戏逻辑处理代码。Update方法是游戏循环的每一帧都去执行,这就要求我们的代码“无时无刻”不在处理所有的可能发生的情况,并做出相应的处理。如果我们想要完成“一段时间”的逻辑代码,例如在游戏中发射一颗子弹,这个过程相对于游戏无限循环的时间来说,非常的短暂,如果我们在Update中去完成这样的逻辑,需要根据时间来进行判断,显然这个完成过程非常的复杂。这个时候,Unity给我们提供了协程,从字面意义上理解就是协助程序的意思,类似于“线程”,帮助我们在主任务进行的同时,需要一些分支任务配合工作来达到最终的效果。但是,协程不是线程,协程依旧是在主线程中进行。Unity中的协程由协程函数和协程调度器两部分构成。通过关键字IEnumerator来定义一个协程(迭代方法),然后再程序中通过StartCoroutine来开启一个协程。

接下来,我们创建一个“SampleScene8”的新创景,然后创建一个“Cube”和一个“CubeCoroutine.cs”的脚本文件,并将他们附加在一起。接下来,我们就在脚本文件中定义一个协程方法,如下所示

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeCoroutine : MonoBehaviour
{
    // Update is called once per frame
    void Update()
    {
        // 按下空格键
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // 启动协程
            StartCoroutine("MoveTest");
        }
    }

    // 定义协程方法
    IEnumerator MoveTest()
    {
        transform.Translate(new Vector3(1, 0, 0));
        yield return null;

        transform.Translate(new Vector3(1, 0, 0));
        yield return null;
    }
}

在上面的代码中,我们使用IEnumerator MoveTest来定义协程方法,方法名称为MoveTest。在协程方法中,我们让Cube沿X轴移动两次,每次移动1个单位长度。然后我们在Update方法中监听空格键的按下,使用StartCoroutine方法来启动协程,方法参数就是协程方法名称。接下来我们就Play当工程,查看运行效果

当我们按下一次空格的时候,Cube会移动两次,每次移动1个单位长度,由于代码执行太快,因此我们看不到两次移动之间的间隔。但是从Inspector检视面板中的X数值可以看到,我们每次按下空格的时候,Cube的确是移动了两个单位的长度。

当然,这样简单的代码并不能展示协程的强大之处。我们先从协程方法里面的return解释一下。在普通方法里面,我们经常使用return方法来返回方法的执行的结果值,但是在协程方法里面,这个return并不是返回结果值。上文代码中的“yield return null;”表示暂停协程等待下一帧继续执行。这样的返回设计,让我们能够控制在指定数量的帧中来执行不同的代码,而不是在所有的帧中执行复杂的条件代码。什么意思呢?

        transform.Translate(new Vector3(1, 0, 0));
        yield return null;

        transform.Translate(new Vector3(1, 0, 0));
        yield return null;

我们的协程方法执行后,会在Update方法中执行transform.Translate(new Vector3(1, 0, 0))代码,也就是让Cueb沿X轴移动1个单位的距离。然后使用yield return null停止协程方法等待下一次Update方法。下一次Update方法执行后,就会执行协程中第二个transform.Translate(new Vector3(1, 0, 0))代码,继续让Cueb沿X轴移动1个单位的距离。然后使用yield return null停止协程方法。至此,协程方法执行完毕。

我们回头思考一下发射子弹的协程该如何实现呢?当我们按下空格键代表发射动作的时候,我们可以启动一个子弹飞行协程,在这个协程方法中,我们可以根据指定的速度和射程来移动子弹,协程结束也就代表子弹的飞行逻辑结束。但是,这个需要借助精确的时间来实现。此时,我们可以借助使用“yield return new WairForSeconds(时间);”来表示等待规定时间后继续执行,这样让我们从时间角度出发来执行我们的代码,而不用考虑他们到底在那一帧中去执行。我们稍微改动我们的代码。

    // 定义协程方法
    IEnumerator MoveTest()
    {
        transform.Translate(new Vector3(1, 0, 0));
        //yield return null;
        yield return new WaitForSeconds(1.0f);

        transform.Translate(new Vector3(1, 0, 0));
        yield return null;
    }

说白了,我们让两次移动间隔1秒钟。接下来,我们在来Play当前工程,查看运行效果

这次当我们按下空格键的时候,两次移动之间由于间隔了1秒钟,因此我们看的比较清楚了。从左边的Inspector检视视图中我们也能够看到X从0变到1,再变到2的过程了。接下来,我们回到子弹发射的问题上来。注意,子弹的速度我们可以固定为一个数值,然后射击的距离也可以固定为一个数值。那么,在那个时间点,子弹飞行到哪里,我们就能够计算出来了。如果觉得1秒钟不精确的话,我们可以减小这个时间,这样子弹位置的更新就比较连续了。最后,协程方法也可以定义形参,那么在使用StartCoroutine调用的时候,可以不使用字符串而直接调用方法。代码如下:

    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(ParamTest(100));
    }

    // 定义包含参数的协程方法
    IEnumerator ParamTest(int x)
    {
        Debug.Log(x);
        yield return null;
    }

运行结果如下:

注意:可以使用 StopCoroutine 和 StopAllCoroutines 来停止协程。 当用 SetActive(false) 禁用某个协程所附加到的游戏对象时,该协程也将停止。调用 Destroy销毁游戏对象时候,也会停止自身的协程。但通过在 MonoBehaviour 实例上将 enabled 设置为 false 来禁用 MonoBehaviour 时,协程不会停止。

总结:协程只启动一次。而后Unity会在后续的update中执行协程中的循环体。有多次循环,就会在多少次update去分别执行循环体代码。说白了,协程就是将一个过程化的行为分解到了update方法中执行。Unity中的协程可以有两种用途:第一,延迟调用;第二,分解操作,把一个过程分解执行。例如,敌人死亡后淡出消失,改变材质颜色透明度即可,让透明度由1变成0,这是一个过程,可以使用协程来实现。再比如,我们可以通过协程进行寻路A点,B点,C端(巡逻)。其实现方式就是协程嵌套协程,一个协程完成从一个点A移动到另一个点B后,本协程结束后再开启下一个协程,然后从当前点B在继续移动到下一个点C。

本课程涉及的内容已经共享到百度网盘:https://pan.baidu.com/s/1e1jClK3MnN66GlxBmqoJWA?pwd=b2id

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

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

相关文章

Vue之render函数

概述 render函数从名字上看就可以看出,它是一个用于渲染的函数,在Vue中我们要将我们写的界面展示到屏幕上时,使用的方式都是组件中的template:标签下编写内容后,由Vue将我们编写的界面渲染到屏幕上。而这个render函数就是比templ…

B. Divide Candies(数学 + 思维)

Problem - B - Codeforces Arkady和他的朋友们喜欢在一个n n的棋盘上玩跳棋。这个棋盘的行和列从1到n编号。 他的朋友们最近赢了一场比赛,所以Actady想用一些糖果来取悦他们。记得一则古老寓言(但不记得寓意)》,Arlady想给他的朋友们每个格子一个糖果组…

SpringMVC学习总结(一)SpringMVC简介入门案例

SpringMVC学习总结(一)SpringMVC简介/入门案例 一、SpringMVC简介 (一)什么是MVC MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分。 M:Model,模型层,指工程中的Ja…

手把手教你学会gitee的注册和代码的提交

欢迎来到壮壮的代码世界 gitee的注册和提交 一、gitee是什么?二、gitee怎么注册三、gitee的一些基本配置四、在gitee上创建远程仓库(存储代码的地方)五、clone远程仓库到本地电脑六、怎么把本地的代码推送到远程仓库去(git的三板斧…

jQuery操作

文章目录 1. jQuery基本介绍1.1 原理示意图1.2 快速入门1.2 什么是jquery对象1.3 dom对象转jQuery对象1.4 jQuery对象转dom对象1.5 jQuery选择器1.5.1 jQuery基本选择器1.5.2 jquery层次选择器1.5.3 基础过滤选择器1.5.4 内容过滤选择器1.5.5 可见度过滤选择器1.5.6 属性过滤选…

Vue(Vue脚手架)

一、使用Vue脚手架(Vue Cli) Vue官方提供脚手架平台选择最新版本: 可以相加兼容的标准化开发工具(开发平台) 禁止:最新的开发技术版本和比较旧版本的开发平台 Vue CLI🛠️ Vue.js 开发的标准工…

AWS VPC 配置指南:快速创建和设置你的虚拟私有云

文章目录 一、前言二、创建 VPC2.1 进入 AWS VPC 服务2.2 创建 VPC2.3 选择所要创建的 VPC 资源2.4 输入 VPC 名称2.5 设置 IPv4 CIDR block(IPv4 CIDR 块)2.6 选择可用区2.7 选择公有子网的数量2.8 设置 NAT 网关和 VPC 终端节点2.9 完成创建 VPC2.10 查…

python ast 详解与用法

目录 基本概念节点类型ast.Assignast.Nameast.Constantast.Callast.Attribute 结点的遍历ast源码示例 结点的修改示例 参考链接 基本概念 python 语言在编译前会解析为抽象语法树,整个文件可以看作一棵树,树上的每个节点就代表一条语句,中序…

计算机中找不到msvcp140.dll无法继续执行代码,解决方法

DLL是Dynamic Link Library的缩写,意为动态链接库。dll文件是电脑系统及软件运行的重要文件,电脑如果丢失dll文件,那么很多软件跟游戏都是无法运行的,msvcp140.dll丢失这个问题就有很多小伙伴遇到,小编今天就分享找不到…

山东专升本计算机第一章-计算机信息技术与计算机文化

计算机信息技术与计算机文化 计算机中的信息表示 数制及其转换 数制:用进位的原则进行计数数码:数制中表示基本数值大小的不同数字符号基数:一种数制所使用的数码个数位权:数码在不同位置的权值 数制的转换 • R进制转化为十进…

【操作系统和强化学习】1.内存管理策略

文章目录 前言1.内存是什么1.1 基本硬件保护措施 碎片1.2 分段机制1.2.1 分段硬件1.3 分页 前言 CPU的调度可以提高CPU的利用率和计算机的响应用户的速度。为了改进性能,应该将多个进程保存在内存中。也就是说必须共享内存。 本文讨论的是如管理内存。 1.内存是什么…

知识变现海哥:我是如何通过知识变现年赚100万的

我叫王海青,大家都称我海哥,是一名知识变现导师,海青教育创始人。从2011年开始,已经从事知识变现培训服务10多年,帮助3000人实现了个人知识技能变现,一直致力于帮助普通人,把自己的一项知识技能…

TiDB实战篇-操作系统参数TiDB Server

操作系统参数 CPU 绿色的是设置cpu用最高的频率去使用cpu。 专门有一个内存给指定的cpu使用。减少cpu的相应时间。 内存 大页的优化,操作系统关闭大页 。 磁盘 TiDB Server配置 cpu 同时多少个会话 如果负载很高那么就往下面调节。 控制优先级(…

计算卸载论文阅读01-理论梳理

标题:When Learning Joins Edge: Real-time Proportional Computation Offloading via Deep Reinforcement Learning 会议:ICPADS 2019 一、梳理 问题:在任务进行卸载时,往往忽略了任务的特定的卸载比例。 模型:针…

BUUCTF ciscn_2019_c_1

小白垃圾做题笔记而已,不建议阅读。 1前期: 其实刚开始拿到程序的时候我还以为是逆向题放错地方了。唉,做题太少了。啥也不会。我是大笨蛋。 题目中用的是ubuntu18,我的ubuntu没怎么用过,vmtools都不能用&#xff0c…

【源码解析】canal核心功能源码解析

1. 项目地址 https://github.com/alibaba/canal.git2. 模块介绍 canal核心模块的功能: deployer模块:独立部署模块,用于canal-server的独立启动,包括本地配置解析、拉取远程配置、启动canal-server。server模块:cana…

山东专升本计算机第六章-数据库技术

数据库技术 SQL数据库与NOSQL数据库的区别 数据库管理系统 考点 6 数据库管理系统的组成和功能 组成 • 模式翻译 • 应用程序的翻译 • 交互式查询 • 数据的组织和存取 • 事务运行管理 • 数据库的维护 功能 • 数据定义功能 • 数据存取功能 • 数据库运行管理…

MySQL备份和恢复

文章目录 一、库的备份和恢复1.库的备份2.库的恢复 二、表的备份和恢复1.表的备份2.表的恢复 备份数据,其实就是生成一个 sql 文件,把创建数据库、创建表、插入数据等各种 SQL 语句都装载到这个文件中。恢复数据,其实就是按顺序执行 sql 文件…

操作系统进程概述、通信

进程 进程就是程序的一次执行过程,同一个程序多次执行对应多个进程; 一、进程的组成 1、PCB (1)进程描述信息:主要是PID等关键信息; (2)进程控制和管理信息; &#xf…

( 数组和矩阵) 566. 重塑矩阵 ——【Leetcode每日一题】

❓566. 重塑矩阵 难度:简单 在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。 给你一个由二维数组 mat 表示的 m x n 矩阵…