Search code examples
c#unity-game-enginecoroutineoculus

Coroutine Not working correctly: only one object is fading in


I've just updated the code. There does Seem to be a problem with wholeRenderer.materials[i].color = Color.Lerp(wholeFadeInColors, wholeFadeOutColors, lerpFactor);. Errors out and I'm struggling to fix it the problem. What could it be?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class InteractionGO: MonoBehaviour
{
    Renderer cutawayRenderer;
    Renderer wholeRenderer;
    Color fadedInColor;
    Color fadedOutColor;
    private const float MIN_FADE = 0.0f;
    private const float MAX_FADE = 1.0f;

    private void Awake()
    {
        fadedInColor = new Color(1f, 1f, 1f, 100f);
        fadedOutColor = new Color(1f, 1f, 1f, 0f);
        wholeRenderer = wholeRenderer.GetComponent<Renderer>();
        cutawayRenderer = cutawayRenderer.GetComponent<Renderer>();
    }

    public void fade()
    {
      StartCoroutine(colorlerpin());
    }

    public IEnumerator colorlerpin()
    {
        // I recommend to setup everything before the loop once to improve perfromance
        // -> collect all full faded-in and faded-out color information

        List<Color> wholeFadeInColors = new List<Color>();
        List<Color> wholeFadeOutColors = new List<Color>();

        foreach (var mat in wholeRenderer.materials)
        {
            // add fadedin color
            wholeFadeInColors.Add(new Color(mat.color.r, mat.color.g, mat.color.b, MAX_FADE));

            // add faded out color
            wholeFadeOutColors.Add(new Color(mat.color.r, mat.color.g, mat.color.b, MIN_FADE));
        }

        List<Color> cutawayFadeInColors = new List<Color>();
        List<Color> cutawayFadeOutColors = new List<Color>();

        foreach (var mat in wholeRenderer.materials)
        {
            // add fadedin color
            cutawayFadeInColors.Add(new Color(mat.color.r, mat.color.g, mat.color.b, MAX_FADE));

            // add faded out color
            cutawayFadeOutColors.Add(new Color(mat.color.r, mat.color.g, mat.color.b, MIN_FADE));
        }

        float ElapsedTime2 = 0.0f;
        float TotalTime2 = 1f;

        while (ElapsedTime2 < TotalTime2)
        {
            var lerpFactor = ElapsedTime2 / TotalTime2;

            // Now apply before stored materials like
            for (int i = 0; i < wholeRenderer.materials.Length; i++)
            {
                wholeRenderer.materials[i].color = Color.Lerp(wholeFadeInColors, wholeFadeOutColors, lerpFactor);
            }

            for (int i = 0; i < wholeRenderer.materials.Length; i++)
            {
                cutawayRenderer.materials[i].color = Color.Lerp(cutawayFadeOutColors, cutawayFadeInColors, lerpFactor);
            }

            ElapsedTime2 += Time.deltaTime;
            yield return null;
        }
    }
}

Solution

  • I recommend doing all expensive stuff only once

    Renderer cutawayRenderer;
    Renderer wholeRenderer;
    Color fadedInColor;
    Color fadedOutColor;
    
    private void Awake()
    {
        fadedInColor = new Color(1f, 1f, 1f, 100f);
        fadedOutColor = new Color(1f, 1f, 1f, 0f);
        wholeRenderer = whole.GetComponent<Renderer>();
        cutawayRenderer = cutaway.GetComponent<Renderer>();
    }
    

    And reuse that. Also why do you increase the ElpasedTime2 twice? your routine yields twice so in one frame only the first object is faded and one frame ater the other one ... what you rather want probably is fading both objects simultanously

    public IEnumerator colorlerpin()
    {
        float ElapsedTime2 = 0.0f;
        float TotalTime2 = 1f;
    
        while (ElapsedTime2 < TotalTime2)
        {
            // you can store the current colors in order to apply them to multiple
            // materials or renderers as well
            // fading out color
            var fadeOutColor = Color.Lerp(fadedInColor, fadedOutColor, (ElapsedTime2 / TotalTime2));
    
            // fading in color
            var fadeInColor = Color.Lerp(fadedOutColor, fadedInColor, (ElapsedTime2 / TotalTime2));
    
            // Now apply those two colors wherever you want
    
            //  fades out main object
            wholeRenderer.material.color = fadeOutColor;
    
            //  fades in new oblect
            cutawayRenderer.material.color = fadeInColor;
    
            ElapsedTime2 += Time.deltaTime;
            yield return null;
        }
    }
    

    However I don't see why one of your objects should be "ignored" since as soon as you do material.color = xy an instance of the material should be created. So unless there is any other script or maybe an Animator also changing this material it should be fine.


    Update

    Since you said you want to apply it to multiple materials I'ld rather setup all Color data beforehand and then only do the necessary lerping inside the loop instead of using new Color all the time

    private const float MIN_FADE = 0.0f;
    private const float MAX_FADE = 1.0f;
    
    public IEnumerator colorlerpin()
    {
        // I recommend to setup everything before the loop once to improve perfromance
        // -> collect all full faded-in and faded-out color information
        List<Color> wholeFadeInColors = new List<Color>();
        List<Color> wholeFadeIOutColors = new List<Color>();
        foreach(var mat in wholeRenderer.materials)
        {
            // add fadedin color
            wholeFadeInColors.Add(new Color(mat.color.r, mat.color.g, mat.color.b, MAX_FADE));
    
            // add faded out color
            wholeFadeOUTColors.Add(new Color(mat.color.r, mat.color.g, mat.color.b, MIN_FADE));
        }
    
        List<Color> cutawayFadeInColors = new List<Color>();
        List<Color> cutawayFadeIOutColors = new List<Color>();
        foreach(var mat in wholeRenderer.materials)
        {
            // add fadedin color
            cutawayFadeInColors.Add(new Color(mat.color.r, mat.color.g, mat.color.b, MAX_FADE));
    
            // add faded out color
            cutawayFadeIOutColors.Add(new Color(mat.color.r, mat.color.g, mat.color.b, MIN_FADE));
        }
    
        float ElapsedTime2 = 0.0f;
        float TotalTime2 = 1f;
    
        while (ElapsedTime2 < TotalTime2)
        {
            var lerpFactor = ElapsedTime2 / TotalTime2;
    
            // Now apply before stored materials like
            var wholeMaterials = wholeRenderer.materials;
    
            for(int i = 0; i < wholeMaterials.Length; i++)
            {
                wholeMaterials[i].color = Color.Lerp(wholeFadeInColors, wholeFadeIOutColors, lerpFactor);
            }
            wholeRenderer.materials = wholeMaterials;
    
    
            var cutawayMaterials = cutawayRenderer.materials;
            for(int i = 0; i < cutawayMaterials .Length; i++)
            {
                cutawayMaterials[i].color = Color.Lerp(cutawayFadeIOutColors, cutawayFadeInColors, lerpFactor );
            } 
            cutawayRenderer.materials = cutawayMaterials;
    
            ElapsedTime2 += Time.deltaTime;
            yield return null;
        }
    }
    

    If you anway only want to use 1,1,1,1 and 1,1,1,0 than offcourse you can completely forget about gathering the colors before and simply only lerp between those two colors.