Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

How can I make the eye blinking in randomly durations ?

Discussion in 'Scripting' started by Chocolade, Jul 7, 2018.

  1. Chocolade

    Chocolade

    Joined:
    Jun 19, 2013
    Posts:
    916
    Inside the Scale method I'm checking if it's in random duration mode:

    Code (csharp):
    1.  
    2. if (randomDuration)
    3.                {
    4.                    scaleCoroutine = StartCoroutine(ScaleOverTime(eyesparts[i], maxSize, Random.Range(0.1f, 1)));
    5.                }
    6.                else
    7.                {
    8.                    scaleCoroutine = StartCoroutine(ScaleOverTime(eyesparts[i], maxSize, duration));
    9.                }
    10.  
    The problem is that it's not completing the blinking before picking up a new random duration that cause the eye to blink too fast or sometimes the minSize not finish before the maxSize since the eye is built from two parts the random duration making the parts not close/open equal.

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class EyeBlinking : MonoBehaviour
    7. {
    8.    public GameObject eyePrefab;
    9.    [Range(0.1f, 50f)]
    10.    public float duration = 1f;
    11.    public Vector3 minSize;
    12.    public Vector3 maxSize;
    13.    public Coroutine scaleCoroutine;
    14.    public bool oppositeDirection = false;
    15.    public bool automatic = false;
    16.    public bool randomDuration = false;
    17.    [Range(1, 20)]
    18.    public int numberOfEyes = 1;
    19.  
    20.    private List<GameObject> eyesparts = new List<GameObject>();
    21.    private bool coroutineIsRunning = false;
    22.    private bool scaleUp = false;
    23.    private float oldDuration;
    24.  
    25.    private void Start()
    26.    {
    27.        oldDuration = duration;
    28.  
    29.        if (oppositeDirection)
    30.        {
    31.            Vector3 tempMin = minSize;
    32.            Vector3 tempMax = maxSize;
    33.  
    34.            minSize = tempMax;
    35.            maxSize = tempMin;
    36.        }
    37.  
    38.        for (int i = 0; i < numberOfEyes; i++)
    39.        {
    40.            GameObject eye = Instantiate(eyePrefab);
    41.            foreach (Transform child in eye.transform)
    42.            {
    43.                child.localScale = minSize;
    44.                eyesparts.Add(child.gameObject);
    45.            }
    46.        }
    47.    }
    48.  
    49.    private void Update()
    50.    {
    51.        if (automatic)
    52.        {
    53.            if (oldDuration != duration && duration >= 0)
    54.            {
    55.                StopAllCoroutines();
    56.                oldDuration = duration;
    57.                Scale();
    58.            }
    59.  
    60.            if (!coroutineIsRunning)
    61.            {
    62.                Scale();
    63.            }
    64.        }
    65.        else
    66.        {
    67.            if (Input.GetKeyDown(KeyCode.G))
    68.            {
    69.                if (duration > 0)
    70.                {
    71.                    StopAllCoroutines();
    72.                    Scale();
    73.                }
    74.            }
    75.        }
    76.    }
    77.  
    78.    private void Scale()
    79.    {
    80.        scaleUp = !scaleUp;
    81.  
    82.        if (scaleCoroutine != null)
    83.            StopCoroutine(scaleCoroutine);
    84.  
    85.        for (int i = 0; i < eyesparts.Count; i++)
    86.        {
    87.            if (scaleUp)
    88.            {
    89.                if (randomDuration)
    90.                {
    91.                    scaleCoroutine = StartCoroutine(ScaleOverTime(eyesparts[i], maxSize, Random.Range(0.1f, 1)));
    92.                }
    93.                else
    94.                {
    95.                    scaleCoroutine = StartCoroutine(ScaleOverTime(eyesparts[i], maxSize, duration));
    96.                }
    97.            }
    98.            else
    99.            {
    100.                scaleCoroutine = StartCoroutine(ScaleOverTime(eyesparts[i], minSize, duration));
    101.            }
    102.        }
    103.    }
    104.  
    105.    private IEnumerator ScaleOverTime(GameObject targetObj, Vector3 toScale, float duration)
    106.    {
    107.        float counter = 0;
    108.        Vector3 startScaleSize = targetObj.transform.localScale;
    109.  
    110.        coroutineIsRunning = true;
    111.  
    112.        while (counter < duration)
    113.        {
    114.            counter += Time.deltaTime;
    115.            targetObj.transform.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
    116.  
    117.            if (counter > duration)
    118.                coroutineIsRunning = false;
    119.  
    120.            yield return null;
    121.        }
    122.    }
    123. }
    124.  
     
  2. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    it's probably line 71 that causing the issue, you're stopping the Coroutine from completing.
    The next issue I see is that you check if duration > 0 on line 69, this will always be true. I don't see that you change duration to anything. I would subtract duration in the coroutine, when the coroutine is complete, then set duration back to 1.

    something easier might be to create a bool, coroutineIsRunning
    check for that on line 71,
    In the coroutine, set the bool to true, when is't complete then you can set it to false
     
    Chocolade likes this.
  3. Chocolade

    Chocolade

    Joined:
    Jun 19, 2013
    Posts:
    916

    The reason in line 71 that I stop all the coroutines is that I wanted to make that if I click on G key fast it will stop the coroutine in the middle and change direction. For example if I clicked on G and it started a coroutine from minSize to maxSize and in the middle before it completed I click on G again it will change it and will scale back to minSize.

    And same if it's from maxSize to minSize the idea is to change the scaling in the middle.

    Maybe you could show me how the code should be with the random part ? And the random part should be working only on the automatic mode not when clicking on G. The G part will stay with constant duration.

    About line 69 you are right I removed the line now. I used this check before using the Range for the duration and forgot to remove it.