Coroutines in Unity

In Unity, there is indeed a relationship between coroutines and the main thread. Coroutines are executed by Unity's main thread (also called the rendering thread).

In Unity, the main thread is a thread responsible for updating game state, processing user input, rendering images and other tasks. Coroutines are special functions that allow us to execute interruptible pieces of code on the main thread. When a coroutine is started, the main thread is also responsible for the execution of the coroutine.

Coroutines pause and resume execution by using the `yield return` statement. When the coroutine reaches the `yield return` statement, it will pause here and return control to the main thread. During this pause, Unity's main thread can handle other tasks, including rendering, physics simulation, processing input, and more. Asynchronous operations (such as resource loading, network requests, etc.) will also continue to execute on the main thread.

Once the conditions for the coroutine to wait (such as the completion of an asynchronous operation) are met, Unity will resume the execution of the coroutine on the main thread and continue executing subsequent code from the position after `yield return`. In this way, the coroutine can switch back and forth between the main thread and asynchronous operations, realizing the collaborative work of asynchronous operations and main thread tasks.

Coroutines are very useful in Unity, especially when it comes to handling asynchronous operations, implementing delays, creating animation sequences, etc. Through coroutines, we can write more readable code, avoid blocking the main thread, and improve application performance and responsiveness.

Summary: Coroutines are executed by the main thread in Unity, and execution is paused and continued through the `yield return` statement. The interaction between coroutines and the main thread makes it possible to handle asynchronous operations in coroutines while maintaining the responsiveness of the application.

Perform asynchronous operations in coroutines

Performing asynchronous operations in coroutines is a method that uses the coroutine mechanism to handle asynchronous tasks. In traditional synchronous programming, when a time-consuming operation is performed, the program waits for the operation to complete before continuing to execute subsequent code. This can cause the application to freeze or become unresponsive while it waits.

To avoid this problem, asynchronous programming patterns were introduced, allowing applications to perform time-consuming operations while continuing to perform other tasks. In asynchronous programming, asynchronous tasks are executed in the background and the main thread or coroutine is notified when completed. This way, we can handle other tasks in the main thread or coroutine without being blocked by time-consuming operations.

In Unity, a coroutine is a special function that can be paused during execution and resume execution at a later time. This makes coroutines ideal for performing asynchronous operations. By using asynchronous operations in coroutines, we can keep the application responsive by yielding execution to the main thread while waiting for the operation to complete.

The general steps for performing asynchronous operations in coroutines are as follows:

1. Start a coroutine: Use the `StartCoroutine` function to start a coroutine, for example: `StartCoroutine(DoAsyncTask())`.

2. Asynchronous operations: Execute asynchronous tasks in coroutines, which may include network requests, file reading and writing, database queries, etc. Asynchronous tasks are usually executed through the asynchronous API provided by Unity, such as `UnityWebRequest` for network requests.

3. Use `yield return` to wait for the asynchronous operation to complete: During the execution of the asynchronous task, we use the `yield return` statement to pause the execution of the coroutine and wait for the asynchronous operation to complete. For example: `yield return www.SendWebRequest()`, where `www` is a `UnityWebRequest` object.

4. Continue execution after the asynchronous operation is completed: Once the asynchronous operation is completed, the coroutine will continue executing subsequent code from the previous pause.

Using coroutines to perform asynchronous operations can help us optimize application performance, improve user experience, and make code easier to write and understand.

Interaction between asynchronous operations and coroutines

Let me explain why asynchronous operations in coroutines do not stop because the coroutine is paused: The interaction between coroutines and asynchronous operations in Unity is achieved by using the `yield return` statement. When using `yield return` in a coroutine to wait for an asynchronous operation to complete, the coroutine does not actually pause the entire execution. Instead, the coroutine will immediately suspend the current execution when encountering a `yield return` statement and return control to Unity's main thread.

During this pause, Unity's main thread can continue to handle other tasks, including handling the execution of asynchronous operations. Asynchronous operations will continue in the background and will not be affected by the suspension of the coroutine. Once the asynchronous operation is completed, Unity will resume the execution of the coroutine on the main thread and continue executing the coroutine code from where it was previously paused.

This mechanism enables asynchronous operations and coroutines to work together, avoiding blocking the main thread, while maintaining code readability and ease of use.

for example:

Suppose we have a coroutine in which an asynchronous operation is to load a resource. The code may look like this:
 

IEnumerator MyCoroutine()
{
    Debug.Log("Coroutine started");
    
    // 异步操作开始
    ResourceRequest request = Resources.LoadAsync("MyResource");
    yield return request; // 协程在这里暂停
    
    // 异步操作完成后继续执行
    Debug.Log("Resource loaded: " + request.asset);
    
    // 继续执行后续逻辑
    Debug.Log("Coroutine finished");
}

In the above code, when execution reaches `yield return request;`, the coroutine will pause execution, but the asynchronous operation `Resources.LoadAsync` still continues to load resources in the background. Once the resource loading is completed, Unity will resume the execution of the coroutine on the main thread, continue to execute subsequent code, and output corresponding log information.

Summary: Asynchronous operations will not be suspended in the coroutine, because the `yield return` statement of the coroutine only suspends the execution of the coroutine itself, and will not affect the continued execution of asynchronous operations in the background. This mechanism enables coroutines to handle asynchronous tasks gracefully, improving the responsiveness and readability of the program.

so 

yield return request;

The function of this line of code is to let Ctrip wait for the data to be loaded before continuing to execute the following code.

ResourceRequest request = Resources.LoadAsync("Level"); 

This line of code is used to asynchronously load the resource named "Level" in the Unity resource file. It is part of the Resource System in Unity and allows you to load resources from the Resources folder.

Let me explain step by step what this line of code does:

1. `Resources`: `Resources` is a special folder that stores resource files (such as prefabs, materials, textures, audio, etc.) in the Unity project. These resources can be loaded at runtime through `Resources.Load()` or `Resources.LoadAsync()`.

2. `LoadAsync("Level")`: The `LoadAsync()` method is an asynchronous resource loading method. It accepts the path or name of a resource as a parameter and starts loading the resource asynchronously. Here, the parameter we pass is "Level", which means we want to load the resource named "Level".

3. `ResourceRequest request`: `ResourceRequest` is an object used for asynchronous resource loading. After calling the `LoadAsync()` method, it will return a `ResourceRequest` object, which is used to track the status of the asynchronous loading operation and obtain the loaded resources.

Once `LoadAsync()` is called, the resource loading process will occur in the background and will not block the main thread. This allows the game to continue with other tasks without having to wait for resources to be loaded.

To use asynchronous loading in a coroutine, you would use `yield return` to wait for the resource to be loaded, as we discussed before:

IEnumerator LoadTable()
{
    ResourceRequest request = Resources.LoadAsync("Level");
    yield return request; // 等待资源加载完成
    
    // 这里可以继续处理加载的资源
    levelData = request.asset as LevelData;
    for (int i = 0; i < levelData.LevelDataList.Count; i++)
    {
        // 处理加载的资源
    }
}

In this way, after the resource loading is completed, the coroutine will continue execution from the position after `yield return request;`, and the loaded resource data can be further processed.

Summary: `Resources.LoadAsync()` is a method for loading resources asynchronously, used to load resources from Unity's Resources folder. By `yield return request;` waiting for the asynchronous loading to complete, we can handle resource loading gracefully in the coroutine and continue to execute subsequent logic after the loading is completed. This mechanism prevents resource loading from blocking the main thread and maintains the smoothness of the game.

Guess you like

Origin blog.csdn.net/qq_74158527/article/details/131988216