The role and usage of coroutines in Unity

Coroutine, that is, Coroutine, can be considered as a function whose return value is IEnumerator, but it needs to be used with StartCoroutine.

Coroutines are not multi-threaded, and all tasks are still completed on the main thread, which is a way of asynchronous multi-tasking.

The advantage of coroutines is that they can be implemented in a function to execute a certain part frame by frame like update, or execute a certain part after a few seconds.

For example, to implement a timer:
insert image description here
the common implementation method is as follows:
insert image description here
this method has two disadvantages. It needs to judge and execute once in each frame, which wastes resources.
Creates a lot of variables and actually only changes one number.

Contrast that with coroutines:
insert image description here
yield return new WaitForSeconds will be called again after a second, executing the rest.

There are two functions to terminate the coroutine, stopCoroutine and stopAllCoroutine.

insert image description here

yield return null is equivalent to continuing to execute the rest of the next frame.

Let's introduce the example from the official tutorial:

public class CoroutinesExample : MonoBehaviour
{
    
    
    public float smoothing = 1f;
    public Transform target;


    void Start ()
    {
    
    
        StartCoroutine(MyCoroutine(target));
    }


    IEnumerator MyCoroutine (Transform target)
    {
    
    
        while(Vector3.Distance(transform.position, target.position) > 0.05f)
        {
    
    
            transform.position = Vector3.Lerp(transform.position, target.position, smoothing * Time.deltaTime);

            yield return null;
        }

        print("Reached the target.");

        yield return new WaitForSeconds(3f);

        print("MyCoroutine is now finished.");
    }

After the coroutine starts to execute, after returning null each time in the loop, it will continue to execute the operations in the loop, and then until the end of the loop, after the loop ends, then execute print "Reached the target.", and then execute yield return new WaitForSeconds (3f);, until 3 seconds later, return to this function again, and then execute print("MyCoroutine is now finished.");.

Let's parse and implement an example using coroutines:
for example, click on a certain position on the screen, and the object will move to that position:

public class PropertiesAndCoroutines : MonoBehaviour
{
    
    
    public float smoothing = 7f;
    public Vector3 Target
    {
    
    
        get {
    
     return target; }
        set//当target被设置的时候将会执行这部分函数
        {
    
    
            target = value;

            StopCoroutine("Movement");
            StartCoroutine("Movement", target);
        }
    }


    private Vector3 target;


    IEnumerator Movement (Vector3 target)
    {
    
    
        while(Vector3.Distance(transform.position, target) > 0.05f)
        {
    
    
            transform.position = Vector3.Lerp(transform.position, target, smoothing * Time.deltaTime);

            yield return null;
        }
    }

Using the coroutine method can realize that the object does not need to poll every frame in the update, which can improve the efficiency.

Click to set the position of the function:
ClickSetPosition

public class ClickSetPosition : MonoBehaviour
{
    
    
    public PropertiesAndCoroutines coroutineScript;


    void OnMouseDown ()
    {
    
    
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        Physics.Raycast(ray, out hit);

        if(hit.collider.gameObject == gameObject)
        {
    
    
            Vector3 newTarget = hit.point + new Vector3(0, 0.5f, 0);
            coroutineScript.Target = newTarget;
        }
    }
}

Add the function of ScreenPointToRay:

Camera.ScreenPointToRay
Description
Returns the ray from the camera through the screen point.

The resulting ray is in world space, starting at the camera's near plane and passing through the (x,y) pixel coordinates of the position on the screen (position.z is ignored).

Screen space is defined in pixels. The lower left corner of the screen is (0,0), and the upper right corner is (pixelWidth -1, pixelHeight -1).

	Camera cam;

    void Start()
    {
    
    
        cam = GetComponent<Camera>();
    }

    void Update()
    {
    
    
        Ray ray = cam.ScreenPointToRay(new Vector3(200, 200, 0));
        Debug.DrawRay(ray.origin, ray.direction * 10, Color.yellow);
    }

The function of Physics.Raycast is to release rays. For example, it can provide the starting point, distance and direction of the emission, and then send rays.
If we want to get some collision-related information, we can declare a rayCastHit variable, which is used to store some collision-related information. of information:

        RaycastHit hit;

insert image description here
You can get a lot of needed information and output the ray information to the ray information variable with the following statement:

      RaycastHit hit;
      Physics.Raycast(ray, out hit);

Guess you like

Origin blog.csdn.net/weixin_43757333/article/details/122843234