Looping a blendhshape (coroutine)

Help me out please. My avatar have a blendshape to open and close eye. So i’m trying to create a routine that will close and open randomly at a predefine pace. I have a working script that is buggy. The following code

  • Does open and close the eye, but the blendshape change instantaniously so i don’t see transition
  • the game become unresponsive at some point (for a second or two, so maybe it’s the yield…

using UnityEngine;
using System.Collections;

public class Blink : MonoBehaviour
{

SkinnedMeshRenderer skinnedMeshRenderer;
bool infiniteBlinking = true;
float blink = 100.0f;
float blendSpeed = 1.0f;
bool eyesClosed = false;

void Awake()
{
    skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
}

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

void Update()
{
    Debug.Log("eyesClosed value is " + eyesClosed);
    Debug.Log("blink value is " + blink);

}

private IEnumerator BlinkEye()
{
    Debug.Log("starting coroutine");
    while (infiniteBlinking == true)
    {
        while (eyesClosed == true && blink <= 100.0f)
        {
            Debug.Log("phase 1 coroutine");

            blendSpeed = 0.1f;
            skinnedMeshRenderer.SetBlendShapeWeight(1, blink);
            blink += blendSpeed; //...increase weight
                                 //eyesClosed = true;
            /*
            */

        }

        while (eyesClosed == false && blink >= 0.0f)
        {
            blendSpeed = 0.5f;
            skinnedMeshRenderer.SetBlendShapeWeight(1, blink);
            blink -= blendSpeed; //...decrease weight
            eyesClosed = false;
            Debug.Log("phase 2 coroutine");

        }
        if (blink >= 100)
        {
            Debug.Log("false trigger coroutine");

            eyesClosed = false;
        }
        if (blink <= 0)
        {
            Debug.Log("true coroutine");

            eyesClosed = true;
        }

        yield return new WaitForSeconds(Random.Range(1.0f, 2.0f)); //...as soon as 1-8 seconds have passed
        //yield return null;
    }

}
// StartCoroutine("Blink"); //restart coroutine

}

This is me learning CoRoutine … i found the solution a few moment after posting and i’ll share the solution and explication. The problem with the initial code is a wrong usage of the while loop. The initial loop is ok, but the second and third one are not. The reason it lag out is because unity is doing nothing but what’s inside the while loop (secondary and third). To solve that, you have to use a IF statement so that the action is done once and then repeated so you can see the actual transition and not just the end result. Here is the solution with a clean code and adjustable speed.

using UnityEngine;
using System.Collections;

public class Blink : MonoBehaviour
{

SkinnedMeshRenderer skinnedMeshRenderer;
bool infiniteBlinking = true;
float blink = 100.0f;
public float EyeOpenSpeed = 15.0f;
public float EyeCloseSpeed = 10.0f;
bool eyesClosed = false;

void Awake()
{
    skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
}

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

void Update()
{
    Debug.Log("eyesClosed value is " + eyesClosed);
    Debug.Log("blink value is " + blink);

}

private IEnumerator BlinkEye()
{
    Debug.Log("starting coroutine");
    while (infiniteBlinking == true)
    {
        if (eyesClosed == true && blink <= 100.0f)
        {
            Debug.Log("phase 1 coroutine");

            blink += EyeOpenSpeed; //...increase weight
            skinnedMeshRenderer.SetBlendShapeWeight(1, blink);
        }

        if (eyesClosed == false && blink >= 0.0f)
        {
            blink -= EyeCloseSpeed; //...decrease weight
            skinnedMeshRenderer.SetBlendShapeWeight(1, blink);
            eyesClosed = false;
            Debug.Log("phase 2 coroutine");

        }
        if (blink >= 100)
        {

            eyesClosed = false;
            yield return new WaitForSeconds(Random.Range(0.5f, 8.0f)); //...as soon as 1-8 seconds have passed

        }
        if (blink <= 0)
        {
            eyesClosed = true;
        }
        yield return null;
    }

}

}