Unity 协程(Coroutine)高级用法实例

文章目录

    • 简介
      • 1. 异步加载场景并显示加载进度
      • 2. 延迟执行与定时器功能
      • 3. 动画序列控制
      • 4. 网络请求处理
      • 5. 渐变颜色或透明度变化
      • 6. 游戏对象的动态移动序列
      • 7. 处理帧率依赖的时间间隔
      • 8. 异步加载资源并在完成后初始化

简介

在Unity中,C#协程(Coroutine)是一种特殊的异步编程机制,它允许我们在不阻塞主线程的情况下执行耗时操作,并且可以按照帧率分阶段地完成任务。以下是5个使用Unity协程的高级用例:

1. 异步加载场景并显示加载进度

IEnumerator LoadSceneAsync(string sceneName)
{
    AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
    
    while (!asyncLoad.isDone)
    {
        float progress = Mathf.Clamp01(asyncLoad.progress / 0.9f); // 考虑到加载过程前0.9的部分代表实际资源加载
        Debug.Log($"Loading Scene: {progress * 100}%");
        
        yield return null; // 让出当前帧,等待下一帧继续检查加载进度
    }
}

void Start()
{
    StartCoroutine(LoadSceneAsync("NextScene"));
}

这个例子展示了如何通过协程异步加载场景,并在加载过程中实时反馈进度。

2. 延迟执行与定时器功能

IEnumerator DelayedAction(float delay, Action action)
{
    float startTime = Time.time;
    
    while (Time.time < startTime + delay)
    {
        yield return null;
    }
    
    action();
}

void UseDelayedAction()
{
    StartCoroutine(DelayedAction(3f, () => 
    {
        Debug.Log("Delayed action executed after 3 seconds.");
    }));
}

在这个案例中,我们创建了一个延迟执行动作的协程,可以在指定时间后执行任意给定的回调函数。

3. 动画序列控制

IEnumerator AnimateSequence(GameObject target, AnimationClip[] clips)
{
    foreach (var clip in clips)
    {
        target.GetComponent<Animator>().Play(clip.name);
        
        while (target.GetComponent<Animator>().GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f)
        {
            yield return null;
        }
    }
    
    Debug.Log("Animation sequence completed.");
}

void PlaySequence()
{
    GameObject character = GameObject.FindWithTag("Player");
    var clips = new AnimationClip[3] { animJump, animIdle, animRun };
    StartCoroutine(AnimateSequence(character, clips));
}

此例说明了如何通过协程按顺序播放一组动画片段,在每个片段播放完毕后切换至下一个片段。

4. 网络请求处理

using UnityEngine.Networking;

IEnumerator FetchData(string url)
{
    UnityWebRequest www = UnityWebRequest.Get(url);
    yield return www.SendWebRequest();

    if (www.result == UnityWebRequest.Result.Success)
    {
        string data = www.downloadHandler.text;
        Debug.Log("Received data: " + data);
        ProcessData(data);
    }
    else
    {
        Debug.LogError("Error: " + www.error);
    }
}

void RequestData()
{
    StartCoroutine(FetchData("http://example.com/data.json"));
}

这个示例展示了如何利用协程处理网络请求,当请求完成时读取返回的数据,并在网络请求期间保持游戏运行流畅。

5. 渐变颜色或透明度变化

IEnumerator FadeInOut(Color startColor, Color endColor, float duration)
{
    float timeElapsed = 0f;
    
    Material mat = GetComponent<Renderer>().material;
    Color currentColor = mat.color;
    
    while (timeElapsed < duration)
    {
        timeElapsed += Time.deltaTime;
        float t = timeElapsed / duration;
        currentColor = Color.Lerp(startColor, endColor, t);
        mat.color = currentColor;
        
        yield return null;
    }
    
    mat.color = endColor;
}

void FadeOut()
{
    StartCoroutine(FadeInOut(Color.white, Color.clear, 2f));
}

在此案例中,协程用于实现颜色或透明度渐变过渡效果,逐渐改变物体的颜色或透明度直至达到目标值。

6. 游戏对象的动态移动序列

IEnumerator MoveToSequence(Transform target, Vector3[] waypoints, float speed)
{
    for (int i = 0; i < waypoints.Length; i++)
    {
        Vector3 destination = waypoints[i];
        
        while (Vector3.Distance(target.position, destination) > 0.1f)
        {
            target.position = Vector3.MoveTowards(target.position, destination, speed * Time.deltaTime);
            yield return null;
        }
        
        // 到达一个点后可以暂停一会儿,增加平滑过渡效果
        yield return new WaitForSeconds(0.2f);
    }
    
    Debug.Log("Move sequence completed.");
}

void StartMoving()
{
    Transform playerTransform = GameObject.FindWithTag("Player").transform;
    Vector3[] path = { new Vector3(0, 0, 0), new Vector3(5, 0, 0), new Vector3(5, 5, 0) };
    StartCoroutine(MoveToSequence(playerTransform, path, 2f));
}

此示例中,协程用于实现游戏对象按照预设路径顺序移动,每到达一个点后等待片刻再继续移动到下一个目标点。

7. 处理帧率依赖的时间间隔

IEnumerator FrameRateIndependentInterval(float realTimeSeconds)
{
    float startTime = Time.time;
    float elapsedTime = 0f;

    while (elapsedTime < realTimeSeconds)
    {
        elapsedTime += Time.deltaTime;
        yield return null;
    }

    Debug.Log("A frame rate independent interval of " + realTimeSeconds + " seconds has passed since start.");
}

void RunFrameRateIndependentAction()
{
    StartCoroutine(FrameRateIndependentInterval(3f));
}

在本例子中,我们创建了一个不受实际帧率影响的定时器,确保无论帧率如何变化,都会在指定的真实时间(例如3秒)之后执行操作。

8. 异步加载资源并在完成后初始化

using UnityEngine.ResourceManagement.AsyncOperations;

IEnumerator LoadAssetAsync<T>(string assetPath, System.Action<T> onLoaded)
{
    AsyncOperationHandle<T> operation = Addressables.LoadAssetAsync<T>(assetPath);

    while (!operation.IsDone)
    {
        yield return null;
    }

    if (operation.Status == AsyncOperationStatus.Succeeded)
    {
        T loadedAsset = operation.Result;
        onLoaded?.Invoke(loadedAsset);
    }
    else
    {
        Debug.LogError($"Failed to load asset at path: {assetPath}");
    }

    Addressables.Release(operation);
}

void InitializeWithLoadedAsset()
{
    StartCoroutine(LoadAssetAsync<GameObject>("Assets/Prefabs/MyPrefab.prefab", prefab =>
    {
        Instantiate(prefab, Vector3.zero, Quaternion.identity);
    }));
}

在这个例子中,使用Unity Addressables异步加载系统加载资源,并在加载完成后通过回调函数进行初始化操作。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt QCustomPlot 鼠标悬浮提示

使用QCustomPlot绘图时&#xff0c;相信大多数童鞋们都会有类似的诉求&#xff1a;希望鼠标移动到节点时&#xff0c;可以显示该节点的数据。这里转载了一篇关于 鼠标悬浮提示 的一篇文章&#xff0c;并对该文章涉及的代码经过了整理&#xff0c;经实践证明是可行的。 鼠标悬浮…

操作系统--Linux内核进程间的通信方式

每个进程的用户地址空间都是独立的&#xff0c;一般而言是不能互相访问的&#xff0c;但内核空间是每个进程都共享的&#xff0c;所以进程之间要通信必须通过内核。 一、管道 匿名管道&#xff1a;它没有名字标识&#xff0c;匿名管道是特殊文件只存在于内存&#xff0c;没有存…

二、Gradle 与 Idea 整合

这里写自定义目录标题 1、Groovy简介2、Groovy 安装3、创建 Groovy 项目4、Groovy 基本语法5、在 idea 中创建普通 java 工程 1、Groovy简介 详细了解请参考&#xff1a;http://www.groovy-lang.org/documentation.html 2、Groovy 安装 下载后解压到本地 验证&#xff1a; …

springboot完成一个线上图片存放地址+实现前后端上传图片+回显

1.路径 注意路径 2.代码&#xff1a;&#xff08;那个imagePath没什么用&#xff0c;懒的删了&#xff09;&#xff0c;注意你的本地文件夹要有图片&#xff0c;才可以在线上地址中打开查看 package com.xxx.common.config;import org.springframework.beans.factory.annotat…

HTML+CSS+JS的3D进度条

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>HTMLCSSJS的3D进度条</title><style>…

高效的跳表

高效的跳表 一、 概念二、 实现原理三、存在的问题四、解决方法五、如何保证效率六、代码实现七、总结对比平衡搜索树对比哈希表 一、 概念 跳表&#xff0c;是一种用来查询数据的数据结构&#xff0c;它是由William Pugh发明的&#xff0c;借助有序链表&#xff0c;来实现高效…

git 小乌龟解决冲突问题

git 解决冲突 下边命令我指的是小乌龟的命令&#xff0c;不是指的git的命令行语句 git commit 提交代码到本地仓库 git pull 拉代码 git push 推代码的时候出现代码冲突问题 自动合并失败了&#xff0c;有冲突的文件&#xff0c;需要先解决冲突。修改标记为已解决&#xff0…

轻松玩转书生·浦语大模型趣味Demo(二)

大模型及 InternLM 模型介绍 什么是大模型 人工智能领域中参数数量巨大&#xff0c;拥有庞大计算能力和参数规模的模型 特点及应用 利用大量数据进行训练拥有数十亿甚至数千亿个参数模型在各种任务中展现出惊人的性能 InternLM-Chat-7B 智能对话 Demo Legant 介绍 lagnet …

Flutter 应用服务:主题、暗黑、国际化、本地化 - app_service库

Flutter应用服务 主题、暗黑、国际化、本地化 app_service库 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/det…

Debezium发布历史103

原文地址&#xff1a; https://debezium.io/blog/2021/03/18/understanding-non-key-joins-with-quarkus-extension-for-kafka-streams/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. 了解 Kafka Streams 的 Q…

2024美赛数学建模A题思路分析 - 资源可用性和性别比例

1 赛题 问题A&#xff1a;资源可用性和性别比例 虽然一些动物物种存在于通常的雄性或雌性性别之外&#xff0c;但大多数物种实质上是雄性或雌性。虽然许多物种在出生时的性别比例为1&#xff1a;1&#xff0c;但其他物种的性别比例并不均匀。这被称为适应性性别比例的变化。例…

书客、米家、柏曼大路灯哪款好?多维度实测对比推荐!

每到寒暑假&#xff0c;各个论坛上出现“大路灯怎么选”的类似话题非常频繁&#xff0c;因为现在的孩子出来上学期间需要读写之外&#xff0c;在寒暑假时也在不断的学习&#xff0c;许多家长关注到孩子学习时的光线问题&#xff0c;担心影响到孩子的视力状况&#xff0c;都纷纷…

pdf怎么标注?这3个标注方法亲测好用

pdf怎么标注&#xff1f;在日常办公中&#xff0c;PDF标注软件发挥着重要作用。当我们收到一份PDF文档&#xff0c;如合同、报告或电子书&#xff0c;需要对其进行批注、修改或解释时&#xff0c;一款好用的PDF标注软件就显得尤为重要。通过这些软件&#xff0c;我们可以轻松地…

【机器学习】贝叶斯垃圾邮件识别

实验三&#xff1a;贝叶斯垃圾邮件识别 本次作业以垃圾邮件分类任务为基础&#xff0c;要求提取文本特征并使用朴素贝叶斯算法进行垃圾邮件识别&#xff08;调用已有工具包或自行实现&#xff09;。 1 任务介绍 ​ 电子邮件是互联网的一项重要服务&#xff0c;在大家的学习、…

操作系统-02-Ubuntu 常用命令等汇总

Ubuntu Ubuntu是一个开源软件平台&#xff0c;可以在从智能手机、平板电脑和个人电脑到服务器和云端等各种设备上运行。 ubuntu Title: Desktop Ubuntu desktop->command: CtrlAltF2~F6 command->desktop: CtrlAltF7 Login Change to root user $ sudu suLogin to al…

springboot 集成 nacos (demo 版)

环境要求&#xff1a;本地安装 nacos&#xff08;windows版本&#xff09;&#xff0c;jdk 是 8&#xff0c;安装完还得在 nacos 上面配置一个 yaml 类型的配置文件&#xff0c;方便项目演示读取。 提示&#xff1a;如标题所示&#xff0c;本文只介绍如何从零到一的去集成 naco…

【C/Python】GtkApplicationWindow

一、C语言 GtkApplicationWindow 是 GTK 库中用于创建应用程序主窗口的一个控件。 首先&#xff0c;需要确保环境安装了GTK开发库。然后&#xff0c;以下是一个简单的使用 GtkApplicationWindow 创建一个 GTK 应用程序的示例&#xff1a; #include <gtk/gtk.h>static …

nvm - nodejs版本管理工具

我们可能同时在进行2个或者多个不同的项目开发&#xff0c;每个项目的需求不同&#xff0c;进而不同项目必须依赖不同版本的NodeJS运行环境&#xff0c;这种情况下&#xff0c;对于维护多个版本的node将会是一件非常麻烦的事情&#xff0c;nvm就是为解决这个问题而产生的&#…

9.2爬楼梯(LC70-E)

算法&#xff1a; 多举几个例子&#xff0c;找规律&#xff1a; 爬到第一层楼梯有一种方法&#xff0c;爬到二层楼梯有两种方法。 那么第一层楼梯再跨两步就到第三层 &#xff0c;第二层楼梯再跨一步就到第三层&#xff08;时序&#xff09;。 所以到第三层楼梯的状态可以由…

k8s存储之PV、PVC

在k8s集群中&#xff0c;资源存储会散落到各个工作节点上&#xff0c;这样对用资源调用很不方便&#xff0c;那么k8s是如何实现存储资源共享的呢&#xff0c;本文浅尝辄止的探讨一下&#xff0c;k8s是通过pv、pvc实现的。 一、PV、PVC的概念 1、持久卷(PV&#xff09; pv是Pe…
最新文章