{"id":893,"date":"2024-09-14T19:53:59","date_gmt":"2024-09-14T11:53:59","guid":{"rendered":"https:\/\/www.huangjiaqi-mise.site\/?p=893"},"modified":"2024-09-14T23:34:16","modified_gmt":"2024-09-14T15:34:16","slug":"building-a-simulation-system-with-unity-coroutines","status":"publish","type":"post","link":"https:\/\/www.huangjiaqi-mise.site\/?p=893","title":{"rendered":"Building a Simulation System with Unity: Coroutines"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"893\" class=\"elementor elementor-893\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-888f1c5 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"888f1c5\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-no\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b08a5f8\" data-id=\"b08a5f8\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-50e3c65 elementor-widget-divider--separator-type-pattern elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"50e3c65\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\" style=\"--divider-pattern-url: url(&quot;data:image\/svg+xml,%3Csvg xmlns=&#039;http:\/\/www.w3.org\/2000\/svg&#039; preserveAspectRatio=&#039;none&#039; overflow=&#039;visible&#039; height=&#039;100%&#039; viewBox=&#039;0 0 20 16&#039; fill=&#039;none&#039; stroke=&#039;black&#039; stroke-width=&#039;1&#039; stroke-linecap=&#039;square&#039; stroke-miterlimit=&#039;10&#039;%3E%3Cg transform=&#039;translate(-12.000000, 0)&#039;%3E%3Cpath d=&#039;M28,0L10,18&#039;\/%3E%3Cpath d=&#039;M18,0L0,18&#039;\/%3E%3Cpath d=&#039;M48,0L30,18&#039;\/%3E%3Cpath d=&#039;M38,0L20,18&#039;\/%3E%3C\/g%3E%3C\/svg%3E&quot;);\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2bde4fe elementor-widget elementor-widget-text-editor\" data-id=\"2bde4fe\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h4>1. What is a Coroutine?<\/h4><p>A coroutine is a special type of function that can be paused and resumed during execution, making it ideal for scenarios where you need to wait for a condition or a certain amount of time. In Unity, coroutines are commonly used to handle time delays, animations, network requests, and other tasks that shouldn\u2019t block the main thread.<\/p><h4>2. Basic Usage<\/h4><h6><span style=\"background-color: var(--ast-global-color-5); color: var(--ast-global-color-3); font-style: inherit;\">(1) Starting a Coroutine:\u00a0<\/span><\/h6><p><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">To start a coroutine, use the <\/span><b style=\"font-style: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">StartCoroutine()<\/b><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">\u00a0method. Coroutines typically return an <\/span><b style=\"font-style: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">IEnumerator<\/b><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">\u00a0type.<\/span><\/p><p><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">Example: <\/span><b style=\"font-style: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">StartCoroutine( MyCoroutine() )<\/b><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">;<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ba21ff9 elementor-widget__width-inherit elementor-widget elementor-widget-html\" data-id=\"ba21ff9\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre>\r\n<code>\r\n<strong>IEnumerator MyCoroutine()<\/strong>\r\n{\r\n    print(\"Starting\");\r\n    yield return new WaitForSeconds(2); \/\/ Wait for 2 seconds\r\n    print(\"Finished\");\r\n}\r\n<\/code>\r\n<\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7202093 elementor-widget elementor-widget-text-editor\" data-id=\"7202093\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h6><span style=\"font-style: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">(2) Defin<\/span><span style=\"font-style: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">ing<\/span><span style=\"font-style: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\"> a Coroutine:<\/span><\/h6><p><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">Inside a coroutine, you can use the <\/span><b style=\"font-style: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">yield<\/b><span style=\"font-style: inherit; font-weight: inherit; background-color: var(--ast-global-color-5); color: var(--ast-global-color-3);\">\u00a0statement to pause execution until a condition is met or a specified time has passed.<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-0d84d98 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"0d84d98\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-no\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-52a4154\" data-id=\"52a4154\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-0c9f202 elementor-widget elementor-widget-text-editor\" data-id=\"0c9f202\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h4>3. Different yield Options:<\/h4><p>Unity provides several types of <b>yield<\/b>\u00a0instructions, the most common being:<\/p><p>&#8211; <b>yield return null;<\/b> : Continues execution in the next frame.<br \/>&#8211; <b>yield return new WaitForSeconds(float seconds);<\/b> : Waits for the specified amount of time.<br \/>&#8211; <b>yield return new WaitForEndOfFrame();<\/b> : Continues execution after the current frame ends.<br \/>&#8211; <b>yield return new WaitUntil(Func predicate);<\/b> : Waits until a specified condition is true.<\/p><h4>4. Advantages of Coroutines<\/h4><h6>(a) Non-blocking Execution:<\/h6><p>Coroutines allow you to run long tasks, like waiting or animations, without blocking the main thread, keeping the game running smoothly.<\/p><h6>(b) Easy to Write and Understand:<\/h6><p>Using coroutines makes code cleaner and avoids callback hell, with logic that closely resembles sequential execution.<\/p><h6>(c) Flexibility:<\/h6><p>Coroutines can distribute tasks across multiple frames, making them suitable for handling complex asynchronous logic.<\/p><h4>5. Important Considerations<\/h4><h6>(a) Lifecycle:<\/h6><p>The coroutine\u2019s lifecycle is tied to the MonoBehaviour component that starts it. If the component is disabled or destroyed, the coroutine will automatically stop.<\/p><h6>(b) Performance:<\/h6><p>Although coroutines are efficient, having too many running at once may impact performance, especially when a large number of coroutines are updated every frame.<\/p><h4>6. Example Application<\/h4>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-47fa224 elementor-widget elementor-widget-html\" data-id=\"47fa224\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre>\n<code>\n<strong>using System.Collections;<\/strong>\n<strong>using System.Collections.Generic;<\/strong>\n<strong>using Unity.VisualScripting;<\/strong>\n<strong>using UnityEngine;<\/strong>\n\npublic class Test : MonoBehaviour\n{\n    bool IsWaitingA;\n    bool IsWaitingB;\n\n\n    \/\/ Start is called before the first frame update\n    void Start()\n    {\n        IsWaitingA = true;\n        IsWaitingB = true;\n        StartCoroutine(Task());\n    }\n\n    \/\/ Update is called once per frame\n    void Update()\n    {\n        if (Input.GetKeyDown(KeyCode.A))\n        {\n            IsWaitingA = false;\n        }\n\n        if (Input.GetKeyDown(KeyCode.B))\n        {\n            IsWaitingB = false;\n        }\n    }\n\n    IEnumerator Task()\n    {\n        while (IsWaitingA)\n        {\n            print(\"Waiting A\");\n            yield return null;\n        }\n        print(\"IsWaitingA ------ > OK\");\n\n        while (IsWaitingB)\n        {\n            print(\"Waiting B\");\n            yield return null;\n        }\n        print(\"IsWaitingB ------ > OK\");\n    }\n}\n<\/code>\n<\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2a31bab elementor-widget elementor-widget-text-editor\" data-id=\"2a31bab\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The above code demonstrates how to use coroutines to manage multiple waiting states. User input controls the flow of the coroutine, making the logic in the game more responsive.<\/p><h4>7. Code Breakdown<\/h4><h6>(1) Field Definitions:<\/h6><p>bool <b>IsWaitingA<\/b>: Controls whether the coroutine is waiting for event A.<br \/>bool <b>IsWaitingB<\/b>: Controls whether the coroutine is waiting for event B.<\/p><h6>(2) Start Method:<\/h6><p>\u00a0When the game starts, both <b>IsWaitingA<\/b>\u00a0and <b>IsWaitingB<\/b>\u00a0are initialized to <b>true<\/b>, indicating that both events are in a waiting state.<br \/>The <b>Task <\/b>coroutine is started.<\/p><h6>(3) Update Method:<\/h6><p>Each frame checks whether the A or B keys are pressed.<br \/>If the A key is pressed, <b>IsWaitingA<\/b>\u00a0is set to <b>false<\/b>, meaning it no longer waits for event A.<br \/>If the B key is pressed, <b>IsWaitingB<\/b>\u00a0is set to <b>false<\/b>, meaning it no longer waits for event B.<\/p><h6>(4) Task Coroutine:<\/h6><p>&#8211; First, it enters the while (<b>IsWaitingA<\/b>) loop:<br \/>&#8211; As long as <b>IsWaitingA<\/b>\u00a0is <b>true<\/b>, it prints &#8220;<b>Waiting A<\/b>&#8220;.<br \/>&#8211; <b>yield return null;<\/b>\u00a0pauses execution, waiting for the next frame.<br \/>&#8211; Once the <b>A key<\/b> is pressed and <b>IsWaitingA<\/b>\u00a0is set to <b>false<\/b>, the loop ends, and it prints <i><b>&#8220;IsWaitingA &#8212;&#8212; &gt; OK&#8221;<\/b><\/i>.<br \/>&#8211; Next, it enters the <b>while (IsWaitingB)<\/b>\u00a0loop:<br \/>&#8211; As long as <b>IsWaitingB<\/b>\u00a0is <b>true<\/b>, it prints &#8220;<b>Waiting B<\/b>&#8220;.<br \/>&#8211; Again, <b>yield return null;<\/b>\u00a0pauses execution until the next frame.<br \/>&#8211; Once the <b>B key<\/b> is pressed and <b>IsWaitingB<\/b>\u00a0is set to <b>false<\/b>, the loop ends, and it prints <i><b>&#8220;IsWaitingB &#8212;&#8212; &gt; OK&#8221;<\/b><\/i>.<\/p><h4><strong>8. Execution Summary<\/strong><\/h4><h6>(1) On Start:<\/h6><p>The script initializes both waiting states to <b>true<\/b>\u00a0and starts the <b>Task<\/b>\u00a0coroutine.<\/p><h6>(2) Waiting for A:<\/h6><p>&#8211; The coroutine first enters the <b>while (IsWaitingA)<\/b>\u00a0loop, continuously printing <b>&#8220;Waiting A&#8221;<\/b>.<br \/>&#8211; Once the A key is pressed, <b>IsWaitingA<\/b>\u00a0becomes <b>false<\/b>, and the coroutine exits the loop, printing <i><b>&#8220;IsWaitingA &#8212;&#8212; &gt; OK&#8221;<\/b><\/i>.<\/p><h6>(3) Waiting for B:<\/h6><p>&#8211; The coroutine then enters the <b>while (IsWaitingB)<\/b>\u00a0loop, continuously printing <b>&#8220;Waiting B&#8221;<\/b>.<br \/>&#8211; Once the B key is pressed, <b>IsWaitingB<\/b>\u00a0becomes <b>false<\/b>, and the coroutine exits the loop, printing <i><b>&#8220;IsWaitingB &#8212;&#8212; &gt; OK&#8221;<\/b><\/i>.<\/p><p><b>This example illustrates how coroutines can be used to manage asynchronous state transitions in a game, controlled by user input. The logic is clean, sequential, and easy to follow, making coroutines a powerful tool for handling non-blocking tasks in Unity.<\/b><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-070841f elementor-widget elementor-widget-text-editor\" data-id=\"070841f\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p><a href=\"https:\/\/www.huangjiaqi-mise.site\/?p=916\" target=\"_blank\">\u3010\u4e2d\u6587\u7248\u8bf7\u70b9\u51fb\u8fd9\u91cc\u3011<\/a><br><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a717d2f elementor-widget-divider--separator-type-pattern elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"a717d2f\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\" style=\"--divider-pattern-url: url(&quot;data:image\/svg+xml,%3Csvg xmlns=&#039;http:\/\/www.w3.org\/2000\/svg&#039; preserveAspectRatio=&#039;none&#039; overflow=&#039;visible&#039; height=&#039;100%&#039; viewBox=&#039;0 0 20 16&#039; fill=&#039;none&#039; stroke=&#039;black&#039; stroke-width=&#039;1&#039; stroke-linecap=&#039;square&#039; stroke-miterlimit=&#039;10&#039;%3E%3Cg transform=&#039;translate(-12.000000, 0)&#039;%3E%3Cpath d=&#039;M28,0L10,18&#039;\/%3E%3Cpath d=&#039;M18,0L0,18&#039;\/%3E%3Cpath d=&#039;M48,0L30,18&#039;\/%3E%3Cpath d=&#039;M38,0L20,18&#039;\/%3E%3C\/g%3E%3C\/svg%3E&quot;);\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>This example illustrates how coroutines can be used to manage asynchronous state transitions in a game, controlled by user input. The logic is clean, sequential, and easy to follow, making coroutines a powerful tool for handling non-blocking tasks in Unity.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[18],"tags":[],"class_list":["post-893","post","type-post","status-publish","format-standard","hentry","category-unity"],"_links":{"self":[{"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=\/wp\/v2\/posts\/893","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=893"}],"version-history":[{"count":28,"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=\/wp\/v2\/posts\/893\/revisions"}],"predecessor-version":[{"id":934,"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=\/wp\/v2\/posts\/893\/revisions\/934"}],"wp:attachment":[{"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=893"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=893"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.huangjiaqi-mise.site\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=893"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}