Search Unity

Do tween Colour changing sequence using list

Discussion in 'Scripting' started by andrew-d1994, Jan 21, 2019.

  1. andrew-d1994

    andrew-d1994

    Joined:
    Apr 28, 2015
    Posts:
    5
    Hello I'm quite new to using DOTweens Sequences. I would like to have a DOTween sequence that I can pass a list of materials for the sequence to change.

    e.g. Simon says type game where a light will light up and the player will press the button. Before the player presses the button the Simon says game will show the player the lights that need to be pressed to complete that round so

    round 1 - red
    round 2 - red then green
    round 3 - red then green then yellow
    etc

    Im trying to set my sequence up so when the game is showing the sequence it will light up each material 1 by 1 waiting for the last to change back to its normal colour before moving on to the next.

    Thank you!
     
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    I wouldn't recommend using DOTween, as it causes some delegate allocation performance issues.
    Running single coroutine would be an easier solution.

    But, if you're really want to use it, make a single sequence.
    Something like this (pseudo-code):
    Code (CSharp):
    1. public void DoRound(List<Material> listPerRound) {
    2.     // Reset your color to initial value
    3.     Sequence seq = DOTween.Sequence();
    4.  
    5.     foreach (Material mat in _yourListPerRound) {
    6.         seq.Append(// Do material color tween);
    7.         seq.Append(// Do initial color tween);
    8.     }
    9.  
    10.     seq.OnComplete(// Do what you want on completion to happen);
    11.     // Play sequence if set to manual mode
    12. }
    When player answers, setup a different list, and do the same thing.
     
  3. andrew-d1994

    andrew-d1994

    Joined:
    Apr 28, 2015
    Posts:
    5
    Hello I have found away to make it work with the code below. Issues I was getting with Coroutine was that it would leave some lights still light up (might be my coding) but my main issues was having each light, light up one after the other I found a lot with loops in a function it would do everything at once which just wasn't working so well, again this could be my lack of coding knowledge. Just out of interest and if you have the spare time how would you go about writing the code inside of a Coroutine? Below is the code i'm currently using and is working rather well.

    Code (CSharp):
    1.     public void ShowNewSequence () {
    2.         simonsLightingSequence = DOTween.Sequence();
    3.         for (int i = 0; i < lightsToBeLit.Count; i++) {
    4.             simonsLightingSequence.Append(lightsToBeLit [i].GetComponent<Renderer>().material.DOColor(Color.white, "_EmissionColor", 0))
    5.                 .InsertCallback(0, () => ToneSelector(lightsToBeLit [i]))
    6.                 .Append(lightsToBeLit [i].GetComponent<Renderer>().material.DOColor(Color.black, "_EmissionColor", 0).SetDelay(1))
    7.                 .AppendInterval(.5f);
    8.         }
    9.         simonsLightingSequence.OnComplete(() => {
    10.             lightingLights = false;
    11.             Debug.Log("Completed lighting");
    12.         });
    13.     }
     
  4. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    It's possible to re-write the whole "tween" thing into single coroutine. It's about the same thing, but it requires more code and it will produce less garbage.

    Something like this (Untested)
    Code (CSharp):
    1. private static int EmissionColor = Shader.PropertyToID("_EmissionColor");
    2. public IEnumerator ShowNewSequence () {
    3.         for (int i = 0; i < lightsToBeLit.Count; i++) {
    4.             var light = lightsToBeLit[i];
    5.             Material mat = light.GetComponent<Renderer>().material;
    6.             mat.SetColor(EmissionColor, Color.white);
    7.  
    8.             ToneSelector(light);
    9.      
    10.             float delay = 1f;
    11.             while (delay > 0) {
    12.                 delay -= Time.deltaTime;
    13.                 yield return null;
    14.             }
    15.  
    16.             mat.SetColor(EmissionColor, Color.black);
    17.  
    18.             delay = 0.5f;
    19.             while (delay > 0) {
    20.                 delay -= Time.deltaTime;
    21.                 yield return null;
    22.             }
    23.        }
    24.  
    25.        lightingLights = false;
    26.        Debug.Log("Completed lighting");
    27. }
    Note that you're not lerping colors in this case, so it's pretty much useless to use dotween.

    If you need to lerp colors, it could be done as following, replacing first delay block:
    Code (CSharp):
    1. float percentage = 0;
    2. float startTime = Time.time;
    3. Color initialColor = mat.GetColor(EmissionColor);
    4. Color currentColor;
    5.  
    6. while (percentage < 1f) {
    7.     percentage = (Time.time - startTime) / *lerpDuration*;
    8.     currentColor = Color.Lerp(initialColor, *endColor*, percentage);
    9.     mat.SetColor(EmissionColor, currentColor);
    10.     yield return null;
    11. }
     
    Last edited: Jan 21, 2019
    FardinHaque and andrew-d1994 like this.
  5. andrew-d1994

    andrew-d1994

    Joined:
    Apr 28, 2015
    Posts:
    5
    That works perfectly! Think I will stick with your way to help reduced the required computing power. Im not 100% what lerping is with colours. I shall go educate my self on that front!

    Sorry for the delay in getting back to you, and thank you for the help :)