Entendiendo las Coroutines (Co-Rutinas) – Unity3D

Entendiendo las Coroutines (Co-Rutinas) – Unity3D

Que son las Co-Rutinas?

Las Co-Rutinas (Coroutines) son métodos que tienen la capacidad de pausarse y reiniciarse exactamente donde se quedo en el frame anterior. Para entenderlo mejor, consideremos el siguiente ejemplo de la documentación oficial :

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

Si quisiéramos hacer una función como la anterior y la colocamos en el Update no tendría ningún efecto fade debido a que la funcion se ejecutara toda en el mismo frame y por ello no se renderizara los estados intermedios entre 1 y 0.

En cambio si la colocáramos dentro de una Co-Rutina de la siguiente manera:

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

La función se pausara en la linea donde esta el yield y el bucle for continuara en el siguiente frame sin perder el valor de la variable f de esta manera en cada frame se renderizara el cambio entre el valor de c.a y c.a -0.1.

Adicionalmente las Co-Rutinas se pueden pausar cada n segundos con la clase WaitForSeconds como vemos en el siguiente ejemplo:

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

Esto es de suma importancia ya que podemos controlar la periodicidad del código de manera que no se ejecute en cada frame como la función Update, sino cada cierto tiempo. Para entender la importancia de este punto ejemplifiquemos el asunto.

Supongamos que estamos creando una clase de AI (inteligencia artificial) y estamos diseñando la característica de Percepción de nuestro actor, si queremos que la clase este constantemente checando la posición de un enemigo, para calcular la distancia del enemigo, o si esta en rango y campo de visión o para verificar con un raycast si esta visible o no, esto podría significar un gasto cuantioso de recursos y podría afectar el rendimiento del juego.

function Percepcion()
{
    for (int i = 0; i < enemies.Length; i++) {
        // implementacion aqui....
    }
}

void Update()
{
    Percepcion();
}

Ahora bien, si usamos una Co-Rutina

IEnumerator Percepcion() {
    for(int i = 0; i < enemies.Length; i++) {
        // implementacion aqui...
        yield return new WaitForSeconds(.5f); // si quieres que la ejecucion se pause en cada iteracion
    }
    //yield return new WaitForSeconds(.5f); // si quieres que la ejecucion se pause despues de completar el bucle
}

la implementación se ejecutara cada medio segundo y no en cada frame lo que representa una disminución significativa en el uso constante de recursos, e impactara de manera positiva en el performance del juego.

Las Co-Rutinas se ejecutan en paralelo?

Esta es una cuestión que siempre se da por sentado (inclusive yo mismo), e investigando un poco sobre este asunto me he percatado que realmente Unity no menciona explicitamente que sea de esa manera, así que me dispuse a hacer unas pruebas para verificar esto.

public class PruebaCoRutinas : MonoBehaviour {

    void Start () {
        StartCoroutine(CoRutina());
    }

    void Update () {
        Debug.Log("Iniciando Update " + Time.frameCount);
    }

    IEnumerator CoRutina()
    {
        for (;;)
        {
            Debug.Log("Desde Corutina " + Time.frameCount);
            yield return new WaitForSeconds(1f);
        }
    }
}

Si ejecutamos el codigo anterior y abrimos la ventana de subprocesos de Visual Studio como se ve en las siguientes imagenes,

captura__03_10_2015__165536
captura__03_10_2015__165536 (2)

notaremos inmediatamente que se ejecutan en el mismo subproceso, lo que prueba que la ejecución de una Co-Rutina en realidad no corre en paralelo.

Espero les haya sido útil el articulo, siéntanse libres de comentar para alguna corrección o sugerencia.

Fuente: Unity Oficial Doc

Deja un comentario