Help with infinite random generated levels.
Hi, I'm making an infinite level that will keep generating random buildings as long the player keeps on the level.
Basically the script generates a random template of the building with a random length and random height for each length, then start to fill with wall/roof/details/etc.
The first script it fills each section with a wall 1x1, so a wall with 5 meters will be filled with 5 instances of the wall. But this was inefficient and cause an FPS drop when spawning.
I made some improvements in the script and now he changes the scale and tile of texture and makes 1 big wall as far as possible. The FPS keeps dropping, but now is like 1/10 of second or less, but is enough to notice while playing.
This is the code:
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class LevelGenerator : MonoBehaviour
{
Vector3 leftSpawner = new Vector3(-10, 0, 0);
Vector3 rightSpawner = new Vector3(10, 0, 0);
GameObject player;
public GameObject buildingPivot;
public GameObject emptyPrefab;
public GameObject groundCivilian;
List<GameObject> roof = new List<GameObject>();
List<GameObject> floor1Details = new List<GameObject>();
List<GameObject> floor1Main = new List<GameObject>();
List<GameObject> floor2Details = new List<GameObject>();
List<GameObject> floor3Details = new List<GameObject>();
List<GameObject> floor4Details = new List<GameObject>();
List<GameObject> supportPillar = new List<GameObject>();
List<GameObject> citizenWall = new List<GameObject>();
List<GameObject> borderBase = new List<GameObject>();
List<GameObject> borderTop = new List<GameObject>();
List<GameObject> borderRoof = new List<GameObject>();
List<GameObject> borderRoot = new List<GameObject>();
float lastBuilding_L = 0;
float lastBuilding_R = 0;
float SPAWNERS_STARTING_POINT = -15;
float BASEHEIGHT = 5f;
float BASELENGHT = 5f;
Vector3 leftCalc;
Vector3 rightCalc;
float leftDist;
float rightDist;
void Start()
{
floor1Details.AddRange(Resources.LoadAll("Floor1/Details").Cast<GameObject>().ToArray());
floor1Main.AddRange(Resources.LoadAll("Floor1/Main").Cast<GameObject>().ToArray());
floor2Details.AddRange(Resources.LoadAll("Floor2").Cast<GameObject>().ToArray());
floor3Details.AddRange(Resources.LoadAll("Floor3").Cast<GameObject>().ToArray());
floor4Details.AddRange(Resources.LoadAll("Floor4").Cast<GameObject>().ToArray());
roof.AddRange(Resources.LoadAll("Roof").Cast<GameObject>().ToArray());
supportPillar.AddRange(Resources.LoadAll("Support_Pillar").Cast<GameObject>().ToArray());
citizenWall.AddRange(Resources.LoadAll("Citizen_Wall").Cast<GameObject>().ToArray());
borderBase.AddRange(Resources.LoadAll("Border1/Border_Base_1").Cast<GameObject>().ToArray());
borderTop.AddRange(Resources.LoadAll("Border1/Border_Top_1").Cast<GameObject>().ToArray());
borderRoof.AddRange(Resources.LoadAll("Border1/Border_Roof_1").Cast<GameObject>().ToArray());
borderRoot.AddRange(Resources.LoadAll("Border1/Border_Root_1").Cast<GameObject>().ToArray());
leftSpawner = new Vector3(leftSpawner.x, leftSpawner.y, leftSpawner.z + SPAWNERS_STARTING_POINT);
rightSpawner = new Vector3(rightSpawner.x, rightSpawner.y, rightSpawner.z + SPAWNERS_STARTING_POINT);
player = GameObject.Find("Player");
GenerateBuilding(50, 5, true);
GenerateBuilding(50, 5, false);
GenerateBuilding(50, 5, true);
GenerateBuilding(50, 5, false);
}
void Update()
{
leftCalc = new Vector3(leftSpawner.x, leftSpawner.y, leftSpawner.z + (lastBuilding_L * BASELENGHT));
rightCalc = new Vector3(rightSpawner.x, rightSpawner.y, rightSpawner.z + (lastBuilding_R * BASELENGHT));
leftDist = Vector3.Distance(player.transform.position, leftCalc);
rightDist = Vector3.Distance(player.transform.position, rightCalc);
if (leftDist < 1000)
{
GenerateBuilding(20, 5, true);
}
if (rightDist < 1000)
{
GenerateBuilding(20, 5, false);
}
}
void GenerateBuilding(int max_lenght, int max_heigth, bool side)
{
Vector3 pivotPos;
int numberOfEmptys = 2;
float slope = Random.Range(-1f, 1f);
if (side)//if in the right or the left side of level
{
pivotPos = new Vector3(leftSpawner.x + slope, leftSpawner.y, leftSpawner.z + (lastBuilding_L * BASELENGHT));
}
else
{
pivotPos = new Vector3(rightSpawner.x + slope, rightSpawner.y, rightSpawner.z + (lastBuilding_R * BASELENGHT));
}
int lastUp = 0;
bool oneFloorUp = false;
bool oneFloorDown = false;
int randLenght = Random.Range(5, max_lenght + 1); // Random Build Lenght
int randHeigth = 0;
int lastHeight = 0;
int MAINDETAILCONSTANT = 25;
int FLOOR1DETAILCONSTANT = 30;
int mainDetailChance = MAINDETAILCONSTANT;
int FLOOR2DETAILCONSTANT = 10;
int floor2DetailChance = FLOOR2DETAILCONSTANT;
int FLOOR3DETAILCONSTANT = 10;
int FLOOR4DETAILCONSTANT = 10;
int floor4DetailChance = FLOOR4DETAILCONSTANT;
int randLargeRoof = Random.Range(0, 3); // Random Large 4th Floor
List<GameObject> buildingList = new List<GameObject>();
GameObject wall = citizenWall[Random.Range(0, citizenWall.Count)]; // random wall
byte randColor = (byte)Random.Range(100, 150);
GameObject pivot = Instantiate(buildingPivot, new Vector3(pivotPos.x, pivotPos.y, pivotPos.z), Quaternion.identity);
int[] segment = new int[randLenght];
/// Creating template
for (int i = 0; i < randLenght; i++)
{
if (i == 0)
{
randHeigth = Random.Range(2, max_heigth + 1); // Random Build Height
}
else
{
if (lastHeight == 2) //Check if current lenght will be -1/0/+1 Height. Will never build less than 2 Lenght
{
randHeigth = lastHeight + Random.Range(0, 2);
if (randHeigth > 0) //oneFloorUp and oneFloorDows is to prevent "serpentine" buildings
{
oneFloorUp = true;
}
else
{
oneFloorUp = false;
oneFloorDown = false;
}
}
else
{
if (oneFloorUp && oneFloorDown)
{
switch (lastUp)
{
case -1:
randHeigth = lastHeight + Random.Range(0, 2);
oneFloorUp = false;
oneFloorDown = true;
break;
case 1:
randHeigth = lastHeight + Random.Range(-1, 1);
oneFloorUp = true;
oneFloorDown = false;
break;
}
}
else
{
randHeigth = lastHeight + Random.Range(-1, 2);
switch (randHeigth - lastHeight)
{
case -1:
lastUp = randHeigth - lastHeight;
oneFloorDown = true;
break;
case 0:
oneFloorUp = false;
oneFloorDown = false;
break;
case 1:
lastUp = randHeigth - lastHeight;
oneFloorUp = true;
break;
}
}
}
}
if (randHeigth > max_heigth)
{
randHeigth = max_heigth;
oneFloorUp = false;
oneFloorDown = false;
}
lastHeight = randHeigth;
segment[i] = randHeigth;
}
//First wall of building, is always a constant wall
GameObject firstWall = Instantiate(wall, new Vector3(pivotPos.x, pivotPos.y + 2.5f, pivotPos.z - 2.5f), Quaternion.Euler(-90, 0, 0));
firstWall.transform.position = new Vector3(firstWall.transform.position.x + (side ? -2.5f : +2.5f), firstWall.transform.position.y * segment[0], firstWall.transform.position.z);
firstWall.transform.localScale = new Vector3(firstWall.transform.localScale.x * 2, firstWall.transform.localScale.y, firstWall.transform.localScale.z * segment[0]);
firstWall.GetComponent<Renderer>().material.mainTextureScale = new Vector2(2, segment[0]);
buildingList.Add(firstWall);
//Second wall of building, is always a constant wall
GameObject secondWall = Instantiate(wall, new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 2.5f, pivotPos.z), Quaternion.Euler(90, (side ? 90 : -90), 0));
secondWall.transform.position = new Vector3(secondWall.transform.position.x, secondWall.transform.position.y * 2, secondWall.transform.position.z + (2.5f * (segment.Length - 1)));
secondWall.transform.localScale = new Vector3(secondWall.transform.localScale.x * segment.Length, secondWall.transform.localScale.y, secondWall.transform.localScale.z * 2);
secondWall.GetComponent<Renderer>().material.mainTextureScale = new Vector2(segment.Length, 2);
buildingList.Add(secondWall);
List<int> lastSegment = new List<int>();
List<int> lastRoofSegment = new List<int>();
for (int i = 0; i < max_heigth; i++)
{
lastSegment.Add(-1);
lastRoofSegment.Add(-1);
}
for (int i = 0; i < segment.Length; i++)
{
for (int j = 0; j < segment[i]; j++)
{
if (i > lastSegment[j])//if i is not the last segment tagged
{
for (int k = i; k < segment.Length; k++)
{
if (segment[k] > j) // if segment if bigger than j, then tag
{
lastSegment[j] = k;
}
else
{
break;
}
}
// Check if will be a large floor
if (j == 3 && randLargeRoof == 0)
{
GameObject halfWall = Instantiate(wall, new Vector3(pivotPos.x + (side ? +3.75f : -3.75f), pivotPos.y + 2.5f + (BASEHEIGHT * j), pivotPos.z - 2.5f + (BASELENGHT * i)), Quaternion.Euler(90, 90, -90));
halfWall.transform.localScale = new Vector3(halfWall.transform.localScale.x / 2, halfWall.transform.localScale.y, halfWall.transform.localScale.z);
buildingList.Add(halfWall);
GameObject fragRoof = Instantiate(roof[0], new Vector3(pivotPos.x + (side ? +4f : -4f), pivotPos.y + 5 + (BASEHEIGHT * j), pivotPos.z), Quaternion.identity);
fragRoof.transform.position = new Vector3(fragRoof.transform.position.x, fragRoof.transform.position.y, fragRoof.transform.position.z + (5 * ((lastSegment[j] + i) / 2f)));
fragRoof.transform.localScale = new Vector3(fragRoof.transform.localScale.x / 2, fragRoof.transform.localScale.y, fragRoof.transform.localScale.z + (5 * (lastSegment[j] - i)));
fragRoof.GetComponent<Renderer>().material.mainTextureScale = new Vector2((lastSegment[j] - i), 1);
buildingList.Add(fragRoof);
GameObject fragWall = Instantiate(wall, new Vector3(pivotPos.x + (side ? +5f : -5f), pivotPos.y + 2.5f, pivotPos.z), Quaternion.Euler(90, (side ? 90 : -90), 0));
fragWall.transform.position = new Vector3(fragWall.transform.position.x, fragWall.transform.position.y + (5 * j), fragWall.transform.position.z + (5f * ((lastSegment[j] + i) / 2f)));
fragWall.transform.localScale = new Vector3(fragWall.transform.localScale.x * (lastSegment[j] - i + 1), fragWall.transform.localScale.y, fragWall.transform.localScale.z);
fragWall.GetComponent<Renderer>().material.mainTextureScale = new Vector2((lastSegment[j] - i + 1), 1);
buildingList.Add(fragWall);
for (int k = i; k < lastSegment[j] + 1; k++)
{
buildingList.Add(Instantiate(supportPillar[0], new Vector3(pivotPos.x + (side ? +3.75f : -3.75f), pivotPos.y - 0.05f + (BASEHEIGHT * j), pivotPos.z + (BASELENGHT * k)), Quaternion.Euler(0, (side ? -90 : 90), 0)));
}
}
else if (j > 1)
{
GameObject fragWall = Instantiate(wall, new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 2.5f, pivotPos.z), Quaternion.Euler(90, (side ? 90 : -90), 0));
fragWall.transform.position = new Vector3(fragWall.transform.position.x, fragWall.transform.position.y + (5 * j), fragWall.transform.position.z + (5f * ((lastSegment[j] + i) / 2f)));
fragWall.transform.localScale = new Vector3(fragWall.transform.localScale.x * (lastSegment[j] - i + 1), fragWall.transform.localScale.y, fragWall.transform.localScale.z);
fragWall.GetComponent<Renderer>().material.mainTextureScale = new Vector2((lastSegment[j] - i + 1), 2);
buildingList.Add(fragWall);
}
}
if (j == segment[i] - 1)//same as segments, but for roof
{
if (i > lastRoofSegment[j])
{
for (int k = i; k < segment.Length; k++)
{
if (segment[k] - 1 == j)
{
lastRoofSegment[j] = k;
}
else
{
break;
}
}
GameObject fragRoof = Instantiate(roof[0], new Vector3(pivotPos.x + (side ? -2.5f : 2.5f), pivotPos.y + 5 + (BASEHEIGHT * j), pivotPos.z + (5f * ((lastRoofSegment[j] + i) / 2f))), Quaternion.identity);
fragRoof.transform.localScale = new Vector3(fragRoof.transform.localScale.x * 2, fragRoof.transform.localScale.y, fragRoof.transform.localScale.z * (lastRoofSegment[j] - i + 1));
fragRoof.GetComponent<Renderer>().material.mainTextureScale = new Vector2((lastRoofSegment[j] - i + 1), 1);
buildingList.Add(fragRoof);
}
}
//if the first segment of the building
if (i == 0)
{
if (j == segment[i] - 1)
{
buildingList.Add(Instantiate(borderTop[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 2.5f + (BASEHEIGHT * j), pivotPos.z - 2.5f), Quaternion.Euler(0, (side ? 135 : -135), 0)));
buildingList.Add(Instantiate(borderRoof[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 5.25f + (BASEHEIGHT * j), pivotPos.z - 2.5f), Quaternion.Euler(0, (side ? 135 : -135), 0)));
}
else
{
buildingList.Add(Instantiate(borderBase[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 2.5f + (BASEHEIGHT * j), pivotPos.z + (BASELENGHT * i) - 2.5f), Quaternion.Euler(0, (side ? 135 : -135), 0)));
}
}
//if the last segment of the building
else if (i == (segment.Length - 1))
{
if (j == segment[i] - 1)
{
buildingList.Add(Instantiate(borderTop[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 2.5f + (BASEHEIGHT * j), pivotPos.z + (BASELENGHT * i) + 2.5f), Quaternion.Euler(0, (side ? 45 : -45), 0)));
buildingList.Add(Instantiate(borderRoof[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 5.25f + (BASEHEIGHT * j), pivotPos.z + (BASELENGHT * i) + 2.5f), Quaternion.Euler(0, (side ? 45 : -45), 0)));
}
else
{
buildingList.Add(Instantiate(borderBase[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 2.5f + (BASEHEIGHT * j), pivotPos.z + (BASELENGHT * i) + 2.5f), Quaternion.Euler(0, (side ? 45 : -45), 0)));
}
}
}
#region Details --------------------------
/// Floor 1
int rand = Random.Range(0, mainDetailChance);
if (rand < 2)
{
mainDetailChance = MAINDETAILCONSTANT;
buildingList.Add(Instantiate(floor1Main[rand], new Vector3(pivotPos.x + (side ? +5f : -5f), pivotPos.y, pivotPos.z + (BASELENGHT * i)), Quaternion.Euler(0, (side ? 0 : 180), 0)));
}
else
{
mainDetailChance--;
int randDetails = Random.Range(0, FLOOR1DETAILCONSTANT);
if (randDetails < floor1Details.Count)
{
buildingList.Add(Instantiate(floor1Details[randDetails], new Vector3(pivotPos.x + (side ? +5f : -5f), pivotPos.y, pivotPos.z + (BASELENGHT * i)), Quaternion.Euler(0, (side ? 0 : 180), 0)));
}
}
/// Floor 2
rand = Random.Range(0, floor2DetailChance);
if (rand < floor2Details.Count)
{
floor2DetailChance = FLOOR2DETAILCONSTANT;
buildingList.Add(Instantiate(floor2Details[rand], new Vector3(pivotPos.x + (side ? +5f : -5f), pivotPos.y + BASEHEIGHT, pivotPos.z + (BASELENGHT * i)), Quaternion.Euler(0, (side ? 0 : 180), 0)));
}
else
{
floor2DetailChance--;
}
/// Floor 3
if (segment[i] >= 4)
{
rand = Random.Range(0, FLOOR3DETAILCONSTANT);
if (rand == 0)
{
if (randLargeRoof == 0 && segment[i] >= 3)
{
int randFloor3 = Random.Range(0, floor3Details.Count);
buildingList.Add(Instantiate(floor3Details[randFloor3], new Vector3(pivotPos.x + (side ? +5.05f : -5.05f), pivotPos.y + (BASEHEIGHT * 3), pivotPos.z + (BASELENGHT * i)), Quaternion.Euler(0, (side ? -90 : 90), 0)));
}
else
{
int randFloor3 = Random.Range(0, floor3Details.Count);
buildingList.Add(Instantiate(floor3Details[randFloor3], new Vector3(pivotPos.x + (side ? 2.55f : -2.55f), pivotPos.y + (BASEHEIGHT * 3), pivotPos.z + (BASELENGHT * i)), Quaternion.Euler(0, (side ? -90 : 90), 0)));
}
}
}
/// Floor 4
if (segment[i] >= 5)
{
if (randLargeRoof == 0)
{
rand = Random.Range(0, floor4Details.Count);
buildingList.Add(Instantiate(floor4Details[rand], new Vector3(pivotPos.x + (side ? +7.5f : -7.5f), pivotPos.y + 15, pivotPos.z + (BASELENGHT * i)), Quaternion.Euler(0, (side ? 0 : 180), 0)));
}
else
{
rand = Random.Range(0, floor4DetailChance);
if (rand < floor4Details.Count)
{
floor4DetailChance = FLOOR4DETAILCONSTANT;
buildingList.Add(Instantiate(floor4Details[rand], new Vector3(pivotPos.x + (side ? +5f : -5f), pivotPos.y + 15, pivotPos.z + (BASELENGHT * i)), Quaternion.Euler(0, (side ? 0 : 180), 0)));
}
else
{
floor4DetailChance--;
}
}
}
#endregion
///////---------------------------------
if (segment[i] > (i == 0 ? 0 : segment[i - 1]) && (i != 0 || i == randLenght - 1)) ///Check if there is a missing wall and place wall and border
{
GameObject missingWall = Instantiate(wall, new Vector3(pivotPos.x + (side ? -2.5f : +2.5f), pivotPos.y + 2.5f + (BASEHEIGHT * (segment[i] - 1)), pivotPos.z + (BASELENGHT * i) - 2.5f), Quaternion.Euler(-90, 0, 0));
missingWall.transform.localScale = new Vector3(missingWall.transform.localScale.x * 2, missingWall.transform.localScale.y, missingWall.transform.localScale.z);
missingWall.GetComponent<Renderer>().material.mainTextureScale = new Vector2(2, 1);
buildingList.Add(missingWall);
buildingList.Add(Instantiate(borderRoof[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 0.25f + (BASEHEIGHT * segment[i]), pivotPos.z + (BASELENGHT * i) - 2.5f), Quaternion.Euler(0, (side ? 135 : -135), 0)));
buildingList.Add(Instantiate(borderTop[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y - 2.5f + (BASEHEIGHT * segment[i]), pivotPos.z + (BASELENGHT * i) - 2.5f), Quaternion.Euler(0, (side ? 135 : -135), 0)));
buildingList.Add(Instantiate(borderRoot[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y - 5.5f + (BASEHEIGHT * segment[i]), pivotPos.z + (BASELENGHT * i) - 2.5f), Quaternion.Euler(0, (side ? 135 : -135), 0)));
}
else if (segment[i] < (i == 0 ? 0 : segment[i - 1]) && (i != 0 || i == randLenght - 1))
{
buildingList.Add(Instantiate(borderRoof[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 5.25f + (BASEHEIGHT * segment[i]), pivotPos.z + (BASELENGHT * i) - 2.5f), Quaternion.Euler(0, (side ? 45 : -45), 0)));
buildingList.Add(Instantiate(borderTop[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y + 2.5f + (BASEHEIGHT * segment[i]), pivotPos.z + (BASELENGHT * i) - 2.5f), Quaternion.Euler(0, (side ? 45 : -45), 0)));
buildingList.Add(Instantiate(borderRoot[0], new Vector3(pivotPos.x + (side ? +2.5f : -2.5f), pivotPos.y - 0.5f + (BASEHEIGHT * segment[i]), pivotPos.z + (BASELENGHT * i) - 2.5f), Quaternion.Euler(0, (side ? 45 : -45), 0)));
}
}
/// Number of emptys segments
for (int i = 1; i < numberOfEmptys + 1; i++)
{
buildingList.Add(Instantiate(emptyPrefab, new Vector3(pivotPos.x, pivotPos.y + 2.5f, pivotPos.z + (BASELENGHT * (randLenght + i)) - 5f), Quaternion.identity));
}
if (side)
{
lastBuilding_L += randLenght + numberOfEmptys;
}
else
{
lastBuilding_R += randLenght + numberOfEmptys;
}
GameObject ground = Instantiate(groundCivilian, new Vector3((side ? -10 : 10), pivotPos.y, pivotPos.z), Quaternion.identity);
ground.transform.position = new Vector3(ground.transform.position.x, ground.transform.position.y * 2, ground.transform.position.z + (2.5f * (segment.Length + 1)));
ground.transform.localScale = new Vector3(ground.transform.localScale.x * 4, secondWall.transform.localScale.y, ground.transform.localScale.z * (segment.Length + 2));
ground.GetComponent<Renderer>().material.mainTextureScale = new Vector2(4, segment.Length + 2);
buildingList.Add(ground);
/// Paint all building tagged objects
foreach (GameObject x in buildingList)
{
x.transform.parent = pivot.transform; // Adding all the building inside of a empty
if (x.tag == "Building")
{
x.GetComponent<Renderer>().material.color = new Color32(randColor, randColor, randColor, 255);
}
if (x.transform.childCount > 0)
{
Transform[] childs = x.gameObject.GetComponentsInChildren<Transform>();
for (int i = 0; i < childs.Length; i++)
{
if (childs[i].tag == "Building")
{
childs[i].GetComponent<Renderer>().material.color = new Color32(randColor, randColor, randColor, 255);
}
}
}
}
buildingList.Clear();
}
}
(I tried without the foreach, but didn't notice a difference)
I don't know where I can improve more in the script, this is a problem since this is only the level without gameplay in action, and all the building is extremely low-poly.
My guess is the script is taking too long in the 3 "for" calculating the length of the wall. I think I made an improvement in the GPU side and a downgrade on the CPU side.
If someone knows what I can do to improve the script, I'll grateful.
Thanks.
Answer by K-Skanz · Sep 23, 2020 at 07:48 PM
One thing that I made that improves (a lot) the performance is changing to URP. I was impressed by how much my game was running more smoothly, but, there's no Ambient Occlusion yet, so... I'll keep developing without URP until they release the AO feature...sad.
i am sorry but i dont see many ways of improving the code without having to rewrite it entirely, my suggestion is to change the GenerateBuilding a coroutine so that there are no frames drop. the way random generating games usually do it is with seeds, in the long run, if this is a game that it is going to get published you sshould probably change totally how you do the scene generation
So, I searched for some random level generator and what they do is instantiate pre-built models at random frequency, this will definitely will stop the drops, but I feel like the scenario will be repetitive. Or maybe I could use this script, generate like 100 buildings, save as prefab, and instantiate them.
As the second option is using seeds, I don't know if I understood correctly, I don't know much about seeds in the generating world, but doing this I would not lose the control of how the buildings are made? I searched not too much about seed generation but looks like all the building will be more "generic". I can be wrong, as I said I don't know much about it.
$$anonymous$$aybe this help to understand what I want to do:
Seeds don't make the game repetitive at all, seeds what give you is control of the random number so that you can simply pool objects in and out rather than instantiating all the time.
Your answer
![](https://koobas.hobune.stream/wayback/20220613011918im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
random number without repeating 1 Answer
How to generate a random 2d world for a 2d endless runner 0 Answers
Random Number every 5 seconds 2 Answers
Help with Randomized Sprite on GUI button click 0 Answers
Randomly generate blocks on a flat map 0 Answers