public IEnumerator ScaleOverSeconds(List<GameObject> objectsToScale, Vector3 scaleTo, float seconds)
{
if (objectsToScale != null)
{
for (int i = 0; i < objectsToScale.Count; i++)
{
float elapsedTime = 0;
Vector3 startingScale = objectsToScale[i].transform.localScale;
while (elapsedTime < seconds)
{
if (objectsToScale == null)
{
yield return null;
}
else
{
objectsToScale[i].transform.localScale = Vector3.Lerp(startingScale, scaleTo, (elapsedTime / seconds));
elapsedTime += Time.deltaTime;
yield return new WaitForEndOfFrame();
}
}
objectsToScale[i].transform.localScale = scaleTo;
}
waitForScaleOver = true;
}
}
Now when I start the coroutine it's scaling one objectsToScale when it finish than it's moving to the next one and scale it and so on. I want to scale them all at the same time in this coroutine.
The full script :
In short : I want to be able to scale multiple objects at the same time automatic or using the R key.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenerateWalls : MonoBehaviour
{
public GameObject gameObjectToRaise;
public float wallsAmount;
public float gap;
public float duration;
public Vector3 raiseAmount;
public bool go = false;
public Color[] colors = new Color[4];
public bool randomColors = false;
public bool autoGenerate = false;
public bool waitForScaleOver = false;
private GameObject wall;
private List<GameObject> walls = new List<GameObject>();
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)
{
CoroutineManager();
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.R))
{
autoGenerate = false;
CoroutineManager();
}
if(autoGenerate)
{
CoroutineManager();
}
}
private void Init()
{
walls = new List<GameObject>();
for (int i = 0; i < wallsAmount; i++)
{
wall = Instantiate(gameObjectToRaise);
wall.transform.position = new Vector3(i + i * gap, 0, i + i * gap);
wall.name = "Walls";
walls.Add(wall);
}
}
private void CoroutineManager()
{
if (waitForScaleOver)
{
for (int i = 0; i < walls.Count; i++)
{
if (raiseAmount.z < 1)
{
raiseAmount.z = 1f;
}
Destroy(walls[i]);
}
Init();
ColorWalls();
StartCoroutine(ScaleOverSeconds(walls, new Vector3(raiseAmount.x, raiseAmount.y,
raiseAmount.z), duration));
waitForScaleOver = false;
}
}
public IEnumerator ScaleOverSeconds(List<GameObject> objectsToScale, Vector3 scaleTo, float seconds)
{
// Do you really need to handle this case?
// You probably want to just not start the coroutine at all
// if you have nothing to scale.
if (objectsToScale == null) yield return null;
Vector3[] startingScale = new Vector3[objectsToScale.Count];
for (int i = 0; i < objectsToScale.Count; i++)
{
// Similar here - shouldn't you just remove null objects first?
if (objectsToScale[i] == null) continue;
startingScale[i] = objectsToScale[i].transform.localScale;
}
for (float t = 0; t < 1f; t += Time.deltaTime / seconds)
{
for (int i = 0; i < objectsToScale.Count; i++)
{
{
if (objectsToScale[i] == null) continue;
objectsToScale[i].transform.localScale = Vector3.Lerp(
startingScale[i],
scaleTo,
t
);
}
yield return null;
}
foreach (var obj in objectsToScale)
obj.transform.localScale = scaleTo;
waitForScaleOver = true;
}
}
private void ColorWalls()
{
var childrenWalls = GameObject.FindGameObjectsWithTag("Wall");
for (int i = 0; i < childrenWalls.Length; i++)
{
if (randomColors)
{
childrenWalls[i].transform.GetChild(0).GetComponent<Renderer>().material.color
= GetRandomColour32();
}
else
{
childrenWalls[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)
);
}
}