0
\$\begingroup\$
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GenerateWalls : MonoBehaviour
{
    public GameObject gameObjectToRaise;
    public float duration;
    public Vector3 raiseAmount;
    public bool go = false;
    public Color[] colors = new Color[4];
    public bool randomColors = false;
    public bool waitForScaleOver = false;

    private GameObject objtoraise;
    private GameObject[] walls;

    private void Start()
    {
        Init();

        ColorWalls();

        // The z Axis must be minimum 1 or any value above 0 could be also 0.1f
        // but it's better to keep it minimum as 1 by default.
        if (raiseAmount.z < 1)
        {
            raiseAmount.z = 1f;
        }

        if (go)
        {
            waitForScaleOver = false;

            StartCoroutine(ScaleOverSeconds(objtoraise, new Vector3(raiseAmount.x, raiseAmount.y,
                raiseAmount.z), duration));
        }
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.R))
        {
            if (waitForScaleOver)
            {
                if (objtoraise != null)
                {
                    if (raiseAmount.z < 1)
                    {
                        raiseAmount.z = 1f;
                    }

                    Destroy(objtoraise);
                    Init();
                    ColorWalls();

                    StartCoroutine(ScaleOverSeconds(objtoraise, new Vector3(raiseAmount.x, raiseAmount.y,
                        raiseAmount.z), duration));

                    waitForScaleOver = false;
                }
            }
        }
    }

    private void Init()
    {
        objtoraise = Instantiate(gameObjectToRaise);
        objtoraise.name = "Walls";

        walls = GameObject.FindGameObjectsWithTag("Wall");
    }

    public IEnumerator ScaleOverSeconds(GameObject objectToScale, Vector3 scaleTo, float seconds)
    {
        if (objectToScale != null)
        {
            float elapsedTime = 0;
            Vector3 startingScale = objectToScale.transform.localScale;
            while (elapsedTime < seconds)
            {
                if (objectToScale == null)
                {
                    yield return null;
                }
                else
                {
                    objectToScale.transform.localScale = Vector3.Lerp(startingScale, scaleTo, (elapsedTime / seconds));
                    elapsedTime += Time.deltaTime;
                    yield return new WaitForEndOfFrame();
                }
            }

            objectToScale.transform.localScale = scaleTo;

            waitForScaleOver = true;
        }
    }

    private void ColorWalls()
    {
        for (int i = 0; i < walls.Length; i++)
        {
            if (randomColors)
            {
                walls[i].transform.GetChild(0).GetComponent<Renderer>().material.color
                    = GetRandomColour32();
            }
            else
            {
                walls[i].transform.GetChild(0).GetComponent<Renderer>().material.color = colors[i];
            }
        }
    }

    private Color32 GetRandomColour32()
    {
        //using Color32
        return new Color32(
          (byte)UnityEngine.Random.Range(0, 255), //Red
          (byte)UnityEngine.Random.Range(0, 255), //Green
          (byte)UnityEngine.Random.Range(0, 255), //Blue
          255 //Alpha (transparency)
        );
    }
}

In the Update I'm using the flag waitForScaleOver and it's working fine I press the R key and than need to wait for the coroutine to finish before the next R pressing will take affect again.

The problem is if I want not to wait for the coroutine to finish so I can press R in the middle and re start the coroutine over and over. It will work if I will not use the flag waitForScaleOver but I want to use the flag because I want to decide if to wait for the coroutine to finish or not when pressing the R key but I can't find the logic with the flag on how to do it.

\$\endgroup\$

2 Answers 2

0
\$\begingroup\$

I'm not sure what are your intention exactly but you can stop the coroutine by saving a reference from the value returned by StartCoroutine then passing that reference to StopCoroutine when WaitForScale is true and the reference to a coroutine is not null

\$\endgroup\$
0
\$\begingroup\$

As Gabriele said you want to save a reference to the coroutine so you can stop when you want to finish it early.

Coroutine scaleCoroutine; // Add this reference to the class

private void Update()
{
    if (Input.GetKeyDown(KeyCode.R))
    {
        if(!waitForScaleOver)
        {
            StopCoroutine(scaleCoroutine);// End the coroutine early here
        }
        
        if (objtoraise != null)
        {
            if (raiseAmount.z < 1)
            {
                raiseAmount.z = 1f;
            }

            Destroy(objtoraise);
            Init();
            ColorWalls();

            scaleCoroutine = StartCoroutine(ScaleOverSeconds(objtoraise, new Vector3(raiseAmount.x, raiseAmount.y,
                raiseAmount.z), duration)); // Update the coroutine reference here when starting the coroutine

            waitForScaleOver = false;
        }
    }
}

Hope this helps as you didn't reply to Gabriele or accepted his answer.

\$\endgroup\$

You must log in to answer this question.

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