Version: 2019.4
Creando y destruyendo GameObjects.
Namespaces

Coroutines (corrutinas)

Cuando usted llama a una función, esta se ejecuta en su totalidad antes de retornar. Esto significa efectivamente que cualquier acción tomando lugar en una función debe suceder en una sola actualización de frame (cuadro); un llamado a una función no puede ser usado para contener una animación procedimental o una secuencia de eventos en el tiempo. Como un ejemplo, considere la tarea de reducir gradualmente el valor alfa (alpha) de un objeto (opacidad) hasta que se convierta completamente invisible.

void Fade() 
{
    for (float ft = 1f; ft >= 0; ft -= 0.1f) 
    {
        Color c = renderer.material.color;
        c.a = ft;
        renderer.material.color = c;
    }
}

Tal como está, la función Fade (Desvanecer) no tendrá el efecto que usted espera. Para que el desvanecimiento sea visible, el alfa debe ser reducido sobre una secuencia de frames (cuadros) para mostrar los valores intermedios siendo renderizados. Sin embargo, la función se ejecutará en su totalidad en una sola actualización de cuadro. Los valores intermedios nunca se verán y el objeto desaparecerá instantáneamente.

Es posible manejar situaciones como estas agregando código a la función Update que ejecuta el desvanecer en una base cuadro-a-cuadro (frame-by-frame). Sin embargo, es usualmente mas conveniente usar una coroutine (corrutina) para este tipo de tarea.

Una corrutina es una función que tiene la habilidad de pausar su ejecución y devolver el control a Unity para luego continuar donde lo dejó en el siguiente frame. En C#, una corrutina es declarada así:

IEnumerator Fade() 
{
    for (float ft = 1f; ft >= 0; ft -= 0.1f) 
    {
        Color c = renderer.material.color;
        c.a = ft;
        renderer.material.color = c;
        yield return null;
    }
}

It is essentially a function declared with a return type of IEnumerator and with the yield return statement included somewhere in the body. The yield return null line is the point at which execution will pause and be resumed the following frame. To set a coroutine running, you need to use the StartCoroutine function:

void Update()
{
    if (Input.GetKeyDown("f")) 
    {
        StartCoroutine("Fade");
    }
}

Notará que el contador en el bucle de la función Fade mantiene su valor correcto durante el tiempo de vida de la corrutina. De hecho, cualquier variable o parametro será preservado correctamente entre los yields.

Por defecto, una corrutina es reanudada en el siguiente frame después de haberse interrumpido (yield), pero también es posible introducir un tiempo de retardo usando WaitForSeconds:-

IEnumerator Fade() 
{
    for (float ft = 1f; ft >= 0; ft -= 0.1f) 
    {
        Color c = renderer.material.color;
        c.a = ft;
        renderer.material.color = c;
        yield return new WaitForSeconds(.1f);
    }
}

Esto se puede utilizar como una forma de difundir un efecto durante un período de tiempo, pero también es una optimización útil. Muchas tareas en un juego deben llevarse a cabo periódicamente y la forma más obvia de hacerlo es incluirlas en la función Update. Sin embargo, esta función generalmente se llamará muchas veces por segundo. Cuando una tarea no necesita repetirse con tanta frecuencia, puede ponerla en una coroutine para obtener una actualización regularmente, pero no en todos los frames. Un ejemplo de esto podría ser una alarma que le avisa al jugador si hay un enemigo cerca. El código podría verse más o menos así:

function ProximityCheck() 
{
    for (int i = 0; i < enemies.Length; i++)
    {
        if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
                return true;
        }
    }
    
    return false;
}

Si hay muchos enemigos, entonces llamar a esta función en cada frame podría introducir una sobrecarga significativa. Sin embargo, podría usar una corrutina para llamarla cada décima de segundo:

IEnumerator DoCheck() 
{
    for(;;) 
    {
        ProximityCheck();
        yield return new WaitForSeconds(.1f);
    }
}

Esto reducirá en gran cantidad el número de comprobaciones llevados a cabo sin ningún efecto notable en la experiencia de juego.

Note: You can stop a Coroutine with StopCoroutine and StopAllCoroutines. A coroutines also stops when the GameObject it is attached to is disabled with SetActive(false). Calling Destroy(example) (where example is a MonoBehaviour instance) immediately triggers OnDisable and the coroutine is processed, effectively stopping it. Finally, OnDestroy is invoked at the end of the frame.

Coroutines are not stopped when disabling a MonoBehaviour by setting enabled to false on a MonoBehaviour instance.

Creando y destruyendo GameObjects.
Namespaces