0
\$\begingroup\$

In the first script I'm doing a reference in the Start for the Colors script: In the Update I did that when i press once on the key C it will StartCoroutine and will change some objects color.

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

public class ObjectsManipulation : MonoBehaviour
{
    //Scaling
    private Scaling scaling;

    //Lights
    public DimLights dimlights;
    private Coroutine lightCoroutine;

    //Colors
    private Colors colors;

    //Rotating
    private Rotating rotating;

    private void Start()
    {
        scaling = GetComponent<Scaling>();
        scaling.Inits();

        colors = GetComponent<Colors>();
        colors.Initis();

        rotating = GetComponent<Rotating>();
    }

    // Use this for initialization
    void Update()
    {
        //Scaling
        if (Input.GetKeyDown(KeyCode.F))
        {
            //Flip the scale direction when F key is pressed
            scaling.scaleUp = !scaling.scaleUp;

            //Stop old coroutine
            if (scaling.scaleCoroutine != null)
                StopCoroutine(scaling.scaleCoroutine);

            if (lightCoroutine != null)
                StopCoroutine(lightCoroutine);


            //Scale  up
            if (scaling.scaleUp)
            {
                //Start new coroutine and scale up within 5 seconds and return the coroutine reference
                rotating.rotateBack = false;
                scaling.scaleCoroutine = StartCoroutine(scaling.scaleOverTime(scaling.objectToScale, scaling.maxSize, scaling.duration));
                lightCoroutine = StartCoroutine(dimlights.dimLightOverTime(1, scaling.duration));
            }

            //Scale Down
            else
            {
                //Start new coroutine and scale up within 5 seconds and return the coroutine reference
                rotating.rotateBack = true;
                scaling.scaleCoroutine = StartCoroutine(scaling.scaleOverTime(scaling.objectToScale, scaling.minSize, scaling.duration));
                lightCoroutine = StartCoroutine(dimlights.dimLightOverTime(0, scaling.duration)); ;
            }
        }

        //Change color
        if (Input.GetKeyDown(KeyCode.C))
        {
            StartCoroutine(colors.ChangeColor());
        }

        //Rotate
        if (Input.GetKey(KeyCode.R) && !scaling.scaleUp)
        {
            rotating.x += Time.deltaTime * rotating.rotationSpeed;
            scaling.objectToScale.transform.localRotation = Quaternion.Euler(0, 0, rotating.x);
            rotating.keyPressed = true;
        }
        if (Input.GetKeyUp(KeyCode.R))
        {
            rotating.keyPressed = false;
        }

        if (!rotating.keyPressed && !scaling.scaleUp && rotating.rotateBack == false
            && DetectInteractable.detected == false)
        {
            scaling.objectToScale.transform.rotation = Quaternion.LookRotation(Camera.main.transform.forward);
        }

        if (DetectInteractable.detected == true && !scaling.scaleUp)
        {
            rotating.x += Time.deltaTime * rotating.rotationSpeed;
            scaling.objectToScale.transform.localRotation = Quaternion.Euler(0, 0, rotating.x);
        }
    }
}

This is the Colors script. I have array of GameObject and i did two foreach loops:

The problem is that it's coloring all the objects at once and I set the colorDuration to 5 seconds. What I want is to color all the objects in the array in 5 seconds in colorDuration. Not each object in the array 5 seconds but all of them together at 5 seconds.

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

public class Colors : MonoBehaviour
{
    public GameObject[] objectsToColor;
    public Color startColor;
    public Color endColor;
    public float colorDuration;

    public void Initis()
    {
        foreach (GameObject rend in objectsToColor)
        {
            startColor = rend.GetComponent<Renderer>().material.color;
        }
        endColor = Color.green;
    }

    public IEnumerator ChangeColor()
    {
        float t = 0;

        while (t < colorDuration)
        {
            foreach (GameObject rend in objectsToColor)
            {
                t += Time.deltaTime;
                rend.GetComponent<Renderer>().material.color = Color.Lerp(startColor, endColor, t / colorDuration);
                yield return null;
            }
        }
    }
}
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Your coroutine is yielding and increasing the time variable with every object you process. What you likely want to do is, in that order:

  1. increase the time variable
  2. update all the objects
  3. and then yield until the next frame

Like this:

while (t < colorDuration) {

    t += Time.deltaTime;    

    foreach (GameObject rend in objectsToColor) {
        rend.GetComponent<Renderer>().material.color = Color.Lerp(startColor, endColor, t / colorDuration);
    }

    yield return null;
 }
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .