更有效的协同程序【插件:More Effective Coroutines】

news2024/11/20 18:43:50

插件地址:传送门

1、命名空间

using System.Collections.Generic;

using MEC;

2、与传统的协程相比

传统:StartCoroutine(_CheckForWin());

被RunCoroutine取代。必须选择执行循环进程,默认为“Segment.Update”。
 


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

public class Test : MonoBehaviour
{
    
    void Start()
    {
        StartCoroutine(_CheckForWin());

        // To run in the Update segment:
        Timing.RunCoroutine(_CheckForWin());
        // To run in the FixedUpdate segment:
        Timing.RunCoroutine(_CheckForWin(), Segment.FixedUpdate);
        // To run in the LateUpdate segment:
        Timing.RunCoroutine(_CheckForWin(), Segment.LateUpdate);
        // To run in the SlowUpdate segment:
        Timing.RunCoroutine(_CheckForWin(), Segment.SlowUpdate);
    }

    IEnumerator<float> _CheckForWin()
    {
        yield return Timing.WaitForSeconds(1);
        Debug.Log("****");
    }
}

3、协程的退出/停止  CancelWith

相当于StopCoroutine,CancelWith确实会增加所有协程生成的不可避免的GC分配的大小大约20个字节。20字节并不大,但是如果您想避免所有可能的GC分配,那么你就可以相对容易地做CancelWith所做的事情,而不用使用这个函数。只是确保在协程中的每个yield return语句之后都做以下检查:if(gameObject != null && gameObject.activeInHierarchy)

public class Cube01 : MonoBehaviour
{

    private void Awake()
    {
       Timing.RunCoroutine(_moveMyButton().CancelWith(gameObject));
    }

    IEnumerator<float> _moveMyButton()
    {
        while (true)
        {
            yield return Timing.WaitForSeconds(1f);
            Debug.Log("********");
        }

    }
}

4、停止和回复协程

MEC协程可以暂停,稍后再恢复。Unity的协程不会这样做,但是概念很简单。

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

public class Cube01 : MonoBehaviour
{
    private CoroutineHandle handleToACoroutine;

    private void Awake()
    {
        handleToACoroutine= Timing.RunCoroutine(_moveMyButton().CancelWith(gameObject));
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            Timing.PauseCoroutines(handleToACoroutine);
        }
        if (Input.GetKeyDown(KeyCode.R))
        {
            Timing.ResumeCoroutines(handleToACoroutine);
        }
    }

    IEnumerator<float> _moveMyButton()
    {
        while (true)
        {
            yield return Timing.WaitForSeconds(1f);
            Debug.Log("********");
        }

    }
}

5、等待直到完成

Unity的默认协同程序有几种情况,你可以产生返回一些变量。例如,你可以“yield return asyncOperation;”。MEC也有这样的功能函数称为WaitUntilDone。

        yield return Timing.WaitUntilDone(wwwObject);
        yield return Timing.WaitUntilDone(asyncOperation);
        yield return Timing.WaitUntilDone(customYieldInstruction);
        // With MEC Pro you can do a little more with WaitUntilDone:
        yield return Timing.WaitUntilDone(newCoroutine);
        // 上面的代码自动启动一个新的协程,并保存当前的协程。
        yield return
        Timing.WaitUntilTrue(functionDelegateThatReturnsBool);  //免费版没有
        yield return
        Timing.WaitUntilFalse(functionDelegateThatReturnsBool); //免费版没有

6、慢更新(slow update)

Unity的协程没有慢更新循环的概念,但MEC的协程有。
慢更新循环(默认情况下)每秒运行7次。它使用绝对时间刻度,所以当你减慢Unity的时间刻度时,它不会减慢SlowUpdate。使用SlowUpdate和总是使用“yield returnTiming.WaitForSeconds(1f/7f);”有两个主要区别。第一个是绝对时间尺度,第二个是所有的SlowUpdate节拍同时发生。

    private void Awake()
    {
        Timing.RunCoroutine(_UpdateTime(), Segment.SlowUpdate);
    }

    private float clock;
    private IEnumerator<float> _UpdateTime()
    {
        while (true)
        {
            //当前段已运行的时间(以秒为单位)。
            clock = Timing.LocalTime;
            yield return 0f;
        }
    }

SlowUpdate还可以很好地检查临时调试变量。例如,如果重建项目需要很长时间,您可以在脚本中设置一个公共bool值,以重置该脚本上的值。您需要定期检查该bool值是否已设置为true,执行该检查的最佳时间是在SlowUpdate上。当用户选中复选框时,它会感觉它立即响应,但它将在你的应用程序中使用更少的处理每1/7秒检查一次,而不是每秒30 - 100次(取决于你的帧率)。

注意:Unity的Time. deltatime变量在SlowUpdate中不会返回正确的值,因为Unity的Time类对这个片段一无所知。可以使用Timing.DeltaTime代替。

您还可以更改SlowUpdate运行的速率。例如:

Timing.Instance.TimeBetweenSlowUpdateCalls = 3f;

上面这行代码将使SlowUpdate每3秒只运行一次。

7、标签【Tag】

在启动协程时,可以选择是否提供标记。标记是标识该协程的字符串。当您标记一个协程或一组协程时,您可以稍后使用KillCoroutine(标签)或KillAllCoroutines(标签)杀死该协程或该组。【API可能会变,可以查看相关API调用】


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

public class Test : MonoBehaviour
{
    void Start()
    {
        Timing.RunCoroutine(_shout(1, "Hello"), "shout");
        Timing.RunCoroutine(_shout(2, "World!"), "shout");
        Timing.RunCoroutine(_shout(3, "I"), "shout2");
        Timing.RunCoroutine(_shout(4, "Like"), "shout2");
        Timing.RunCoroutine(_shout(5, "Cake!"), "shout2");
        Timing.RunCoroutine(_shout(6, "Bake"), "shout3");
        Timing.RunCoroutine(_shout(7, "Me"), "shout3");
        Timing.RunCoroutine(_shout(8, "Cake!"), "shout3");
        Debug.Log("Killed " + Timing.KillCoroutines("shout2"));
 
    }
    IEnumerator<float> _shout(float time, string text)
    {
        yield return Timing.WaitForSeconds(time);
        Debug.Log(text);
    }
}

 8、LocalTime and DeltaTime

Unity的Time. deltatime变量在SlowUpdate中不会返回正确的值,因为Unity的Time类对这个片段一无所知。可以使用Timing.DeltaTime代替。Unity中的默认Time类在大多数情况下都可以正常工作,但在SlowUpdate中无法正常工作。

9、其它的功能【Additional Functionality】

Timing对象中还包含三个辅助函数:CallDelayed、callcontinuous和callperiodic。

(1)CallDelayed: 在一定秒数后调用指定的动作。

(2)CallContinously:每帧连续调用动作,持续数秒。

(3)CallPeriodically:周期性地每隔“x”秒调用动作,持续数秒。

这三种功能都可以很容易地使用协程创建,但是这个基本功能最终被忽略了由于使用频繁,我们将其包含在基本模块中。


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

public class Test : MonoBehaviour
{

    private void Start()
    {
        // 2秒后启动_RunFor5Seconds。
        Timing.CallDelayed(2f, delegate
        {
            Timing.RunCoroutine(_RunFor5Seconds(Timing.RunCoroutine(Test01())));
        });

        // 使物体以每秒一个世界单位的速度向前推进,持续4秒。
        Timing.CallContinuously(4f, delegate {PushOnGameObject(Vector3.forward);}, 
            Segment.FixedUpdate);

        // 尽量不要对callcontinuous进行闭包是非常重要的,因为这将导致每帧都进行GC分配。
        Timing.CallContinuously<Vector3>(Vector3.forward, 4f,
         vector => PushOnGameObject(vector), Segment.FixedUpdate);

    }

    private void PushOnGameObject(Vector3 amount)
    {
        transform.position += amount * Time.deltaTime;
    }


    private IEnumerator<float> _RunFor5Seconds(CoroutineHandle waitHandle)
    {
        Debug.Log("Yielding 5s..");
        yield return Timing.WaitUntilDone(waitHandle);
        Debug.Log("Starting 5 second run.");
        yield return Timing.WaitForSeconds(5f);
        Debug.Log("Finished 5 second run.");
    }

    private IEnumerator<float> Test01()
    {
        yield return Timing.WaitForOneFrame;
        Debug.Log("********");
    }
}

10、链式结构 【Fluid Architecture】

// 常规

Timing.RunCoroutine(_Foo().CancelWith(gameObject));

// MEC的链式

_Foo().CancelWith(gameObject).RunCoroutine();

请记住:与运行协程的其他方式一样,如果您忘记使用RunCoroutine,编译器不会报错,但它不会执行协程。当对Run的调用位于行尾时,这个事实可能有点难以记住。还要记住,这种流畅的语法可能会让其他习惯使用Unity默认协同程序的开发人员感到困惑,因为Unity的默认协同程序API不支持这种语法。

QA:

问:MEC有WaitForEndOfFrame函数吗?
它没有在MEC Free中实现,但MEC Pro有一个部分。
注意:关于WaitForEndOfFrame的实际作用有一些混淆。当你只是想屈服到下一帧时,WaitForEndOfFrame不是一个理想的命令,最好使用“yield return null;”。许多人在使用Unity的协程时使用WaitForEndOfFrame,因为这是他们在Unity的默认协程中最接近WaitForOneFrame的东西,他们没有意识到这可能会导致微妙的问题。MEC定义了常数Timing。WaitForOneFrame,所以在MEC中,如果你愿意,你可以使用显式变量名,而不会产生使用EndOfFrame可能导致的视觉故障和性能下降的可能性。

问:MEC有StopCoroutine的功能吗?
是的。它叫做Timing.KillCoroutines()。它可以接受前一个Timing返回的协程的句柄。RunCoroutine命令,或者它可以接受一个标记。
注意:KillCoroutine用于从不同的函数中停止协程函数。如果你想从协程的函数内部结束协程,那么最好的命令是“yieldbreak;”,这相当于在任何其他函数中调用“return;”。yield break更好的原因是因为KillCoroutine命令不能结束当前正在运行的协程函数,因此该函数将继续执行,直到下一个yield命令,但yield break没有这个问题。

问:MEC有StopAllCoroutines函数吗?
是的。Timing.KillCorutines()。如果你想暂时停止一切,你也可以使用Timing.PauseCorutines()和Timing.ResumeAllCorutines()。

问:MEC是否有一个函数使一个协程在另一个协程完成之前生成?
是的。在你想要持有的协程内部,你调用"yield return Timing.WaitUntilDone(coroutineHandle);"无论何时调用Timing.RunCoroutine,都会返回句柄。

问:MEC完全删除GC分配吗?
答:不是。MEC删除所有逐帧GC分配。(除非你在协程内部的堆上分配内存,但MEC无法控制这一点。)当协程第一次创建时,函数指针和传递给它的任何变量都被放在堆上,最终必须由垃圾收集器清理。这种不可避免的分配发生在Unity的协程和MEC协程中。MEC协程平均分配的垃圾确实比Unity协程少。

问:MEC协程总是比Unity协程内存效率更高吗,还是只有在特定情况下才如此?
答:MEC协程在所有情况下都比Unity协程产生更少的GC分配,除非你分配大字符串并将其作为协程的标记

案例:

void Start ()
 {
 CoroutineHandle handle = 
Timing.RunCoroutine(_RunFor10Seconds());
 handle = Timing.RunCoroutine(_RunFor1Second(handle));
 Timing.RunCoroutine(_RunFor5Seconds(handle));
 }
 private IEnumerator<float> _RunFor10Seconds()
 {
 Debug.Log("Starting 10 second run.");
 
 yield return Timing.WaitForSeconds(10f);
 Debug.Log("Finished 10 second run.");
 }
 private IEnumerator<float> _RunFor1Second(CoroutineHandle
waitHandle)
 {
 Debug.Log("Yielding 1s..");
 yield return Timing.WaitUntilDone(waitHandle);
 Debug.Log("Starting 1 second run.");
 yield return Timing.WaitForSeconds(1f);
 Debug.Log("Finished 1 second run.");
 }
 private IEnumerator<float> _RunFor5Seconds(CoroutineHandle
waitHandle)
 {
 Debug.Log("Yielding 5s..");
 yield return Timing.WaitUntilDone(waitHandle);
 Debug.Log("Starting 5 second run.");
 yield return Timing.WaitForSeconds(5f);
 Debug.Log("Finished 5 second run.");
 }

 

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

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

相关文章

华为OD机试真题 JavaScript 实现【最优资源分配】【2023Q1 200分】

一、题目描述 某块业务芯片最小容量单位为 1.25G&#xff0c;总容量为 M*1.25G&#xff0c;对该芯片资源编号为 1&#xff0c;2&#xff0c;… M。 该芯片支持 3 种不同的配置&#xff0c;分别为 A、B、C. 配置 A: 占用容量为 1.25 * 1 1.25G配置 B: 占用容量为 1.25* 2 2…

一文了解智能驾驶架构平台ROS2和自适应AUTOSAR之间的区别

公众号致力于点云处理&#xff0c;SLAM&#xff0c;三维视觉&#xff0c;高精地图等领域相关内容的干货分享&#xff0c;欢迎各位加入&#xff0c;有兴趣的可联系dianyunpcl163.com。未经作者允许请勿转载&#xff0c;欢迎各位同学积极分享和交流。 背景介绍 在汽车行业&#x…

有人问高考能改变命运不,老大爷回答是不能

昨天看到一段小视频&#xff0c;问高考能改变命运不&#xff0c;老大爷回答是不能。 我遂想起写写这个话题。 &#xff08;1&#xff09; 成功者的要素到底是什么&#xff1f; 我们中国人经常用&#xff1a;成者为王败者为寇&#xff0c;这句话来形容成功者。 我们见过很多成功…

警惕超声波工艺对晶振造成损伤

超声波技术被广泛应用于工业生产中&#xff0c;常见的超声波工艺有&#xff1a;超声波清洗工艺、焊接工艺。 使用该两种工艺时&#xff0c;超声波仪器通常以20KHz至60KHz的频率运行。 清洗工艺是指清除工件表面上液体或固体的污染物&#xff1b;而焊接工艺中&#xff0c;高频机…

论不同阶段的教育”焦虑“

有了孩子&#xff0c;父母们大体对其教育都会有点焦虑感。焦虑是一种情绪&#xff0c;但这里不分析情绪&#xff0c;而是在文题中加了引号&#xff0c;拆开来讨论下不同阶段教育的焦点与考虑。 学前 教育的焦虑在上小学前就开始了&#xff0c;担心起跑线落后了。德国和美国都做…

直播回顾|走进元服务,携手小强停车探索鸿蒙新流量阵地

本期直播《“元”来如此&#xff0c;“服务”直达——揭秘鸿蒙新流量阵地》聚焦元服务的商业流量价值&#xff0c;介绍元服务提供的服务直达和卡片动态变化等轻量化服务。网约停车旗舰平台小强停车做客直播间&#xff0c;分享小强停车在HarmonyOS生态中&#xff0c;如何通过元服…

数据库信息速递 SQL Server新版本许可证价格上涨了10%

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

STM32单片机蓝牙APP GSM短信安全监控系统湿度烟雾入侵报警系统

实践制作DIY- GC0147---蓝牙APP GSM短信安全监控系统 基于STM32单片机设计---蓝牙APP GSM短信安全监控系统 二、功能介绍&#xff1a; 硬件组成&#xff1a;STM32F103C系列最小系统板 LCD1602显示器DHT11空气湿度传感器MQ2烟雾传感器红外热释电人体检测模块SIM800短信发送模块…

记录--详解 XSS(跨站脚本攻击)

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言&#xff1a;我们知道同源策略可以隔离各个站点之间的 DOM 交互、页面数据和网络通信&#xff0c;虽然严格的同源策略会带来更多的安全&#xff0c;但是也束缚了 Web。这就需要在安全和自由之间找…

基于短期替代变量的因果效应估计

本篇文章分为&#xff1a; 1.前言 2.模型方案 2.1 替代指数背景 2.2 替代指数的基本设定 2.3 模型结构 3.评估 4.总结与展望 1. 前言 在网约车双边交易市场中&#xff0c;量化策略对平衡市场供需的影响起着重要的作用。对市场供需的影响分为两种情况&#xff1a; 短期价值…

【Linux】Linux环境与历史

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 1.Linux发展史 a.是什么&#xff1f; b.计算机发展(硬件) 硅谷模式: c.操作系统的故事(软件) 计算机软硬件发展史: d.Linux操作系统 2.Linux提炼特征 a.开源 b.更多…

java设计模式之:组合模式

文章目录 1、什么是组合模式&#xff1f;2、组合模式定义3、组合模式通用代码实现4、组合模式优点5、组合模式应用场景 相信树形结构大家都知道&#xff0c;但是你是否知道用到了什么设计模式吗&#xff1f; 1、什么是组合模式&#xff1f; Compose objects into tree structu…

第二章 翻译

第二章 翻译 2010年真题&#xff08;主旨词&#xff1a;sustainability&#xff09; Section Ⅲ Translation Directions: In this section, there is a text in English. Translate it into Chinese. Write your translation on ANSWER SHEET 2. (15points) “Sustainabili…

转转前端周刊第六十九期

转转前端周刊 本刊意在将整理业界精华文章给大家&#xff0c;期望大家一起打开视野 如果你有发现一些精华文章想和更多人分享&#xff0c;可以点击我们的公众号名称&#xff0c;将文章链接和你的解读文案发给我们&#xff01;我们会对内容进行筛选和审核&#xff0c;保留你的推…

【Rust日报】2023-06-11 Rust 中的 Telegram Bot 框架

MOBOT 的第一个版本&#xff0c;这是一个 Rust 中的 Telegram Bot 框架 这是我一直在研究的 Rust 中的 Telegram Bot 框架。我尝试了其他 Rust 库&#xff0c;但我发现它们对于我正在构建的机器人类型来说过于原始或过于具体。 它带有 Telegram Bot API 的完全原生实现&#xf…

最新前端技术趋势

本文作者系360奇舞团前端开发工程师 前端的车轮滚滚向前&#xff0c;轮子造的越来越圆&#xff0c;速度造的越来越快&#xff0c;每个人都在适应这个轮子的节奏&#xff0c;稍微不注意就会被甩出车轮之外。狼狈不堪之外还会发自心底的大喊一声&#xff1a;别卷了&#xff01;&a…

数据空间基础设施的技术挑战及数联网解决方案

数据空间基础设施的技术挑战及数联网解决方案 罗超然1,2, 马郓1,2,3, 景翔1,2,4&#xff0c;黄罡1,2,5 1 数据空间技术与系统全国重点实验室&#xff0c;北京 100091 2 北京大数据先进技术研究院&#xff0c;北京 100091 3 北京大学人工智能研究院&#xff0c;北京 100871 4 北…

学了三年,一文告诉你物联网到底如何实现万物互联?

前言&#xff1a;作为计算机相关专业的你&#xff0c;绝对听说过物联网这个词&#xff0c;它的解释相比你也听过&#xff0c;叫万物互联&#xff0c;也就是所谓的IOT&#xff0c;但是说实话它到底如何实现的万物互联的你可能还真不知道。不是每个物体都有一个网络接口或者实体接…

线程同步(二)

目录 死锁 加锁之后忘记解锁&#xff1a; 重复加锁&#xff0c;造成死锁 在程序中有多个共享资源&#xff0c;因此有很多把锁&#xff0c;随意加锁&#xff0c;导致相互被阻塞 在使用多线程编程的时候&#xff0c;如何避免死锁呢&#xff1f; 读写锁 在程序中对读写锁加…

Rust每日一练(Leetday0029) 柱状图、最大矩形、扰乱字符串

目录 84. 柱状图中最大的矩形 Largest-rectangle-in-histogram &#x1f31f;&#x1f31f;&#x1f31f; 85. 最大矩形 Maximal Rectangle &#x1f31f;&#x1f31f;&#x1f31f; 87. 扰乱字符串 Scramble String &#x1f31f;&#x1f31f;&#x1f31f; &#x1…