Reputation: 21
I am trying to make a procedural city generate but all of the buildings in the same group are facing the same direction (rotated the same) and are the same scale. I am trying to add variation in height and rotation so it looks more random. This is what I have so far but maybe I am going about this all the wrong way. I am new to programming so I appreciate any help you guys could give. Thank you!
public GameObject[] buildings;
public int mapWidth = 20;
public int mapHeight = 20;
int buildingFootprint = 45;
float randomY = Random.Range(-360f, 360f);
// Procedural Generation
void Start ()
{
float seed = Random.Range(0, 500);
for (int h = 0; h < mapHeight; h++)
{
for (int w = 0; w < mapWidth; w++)
{
int result = (int)(Mathf.PerlinNoise(w/3.0f + seed, h/3.0f + seed) * 50);
Vector3 pos = new Vector3(w * buildingFootprint, 10, h * buildingFootprint);
Vector3 rot = new Vector3(0, randomY, 0);
if (result < 5)
Instantiate(buildings[0], pos, Quaternion.Euler(rot));
else if (result < 10)
Instantiate(buildings[5], pos, Quaternion.Euler(rot));
else if (result < 15)
Instantiate(buildings[6], pos, Quaternion.Euler(rot));
else if (result < 20)
Instantiate(buildings[1], pos, Quaternion.Euler(rot));
else if (result < 30)
Instantiate(buildings[2], pos, Quaternion.Euler(rot));
else if (result < 40)
Instantiate(buildings[3], pos, Quaternion.Euler(rot));
else if (result < 50)
Instantiate(buildings[4], pos, Quaternion.Euler(rot));
}
}
}
Upvotes: 0
Views: 1012
Reputation: 1256
It's because you set their rotation to Quaternion.identity
The identity rotation (Read Only).
This quaternion corresponds to "no rotation" - the object is perfectly aligned with the world or parent axes.
Set it to random rotation like this (I'm assuming you want to rotate them on Y axis):
// getting random rotation
float randomY = Random.Range(-360f, 360f);
// assigning random rotation to Y axis
Vector3 rot = new Vector3(0, randomY, 0);
// instantiating random building on position `pos` and rotation `rot`, I used `Quaternion.Euler` to convert the Vector3 to Quaternion
Instantiate(buildings[index], pos, Quaternion.Euler(rot));
For scaling you need to decide if you want to scale them uniformly or you want to have random scale on every axis. It would look something like this:
// getting random scale
Vector3 scale = Vector3.one;
if(scaleUniform)
{
float randomScale = Random.Range(min, max);
scale = new Vector3(randomScale, randomScale, randomScale);
}
else
{
scale = new Vector3(Random.Range(min, max), Random.Range(min, max), Random.Range(min, max));
}
// instantiating random building on position `pos` and rotation `rot`, I used `Quaternion.Euler` to convert the Vector3 to Quaternion
GameObject building = Instantiate(buildings[index], pos, Quaternion.Euler(rot));
// set the scale
building.localScale = scale;
Ultimately you should end up with a code like this:
public GameObject[] buildings;
public int mapWidth = 20;
public int mapHeight = 20;
int buildingFootprint = 45;
bool scaleUniform = true;
// Procedural Generation
void Start ()
{
float seed = Random.Range(0, 500);
for (int h = 0; h < mapHeight; h++)
{
for (int w = 0; w < mapWidth; w++)
{
int result = (int)(Mathf.PerlinNoise(w/3.0f + seed, h/3.0f + seed) * 50);
float randomY = Random.Range(-360f, 360f); // get random rotation for Y axis
Vector3 pos = new Vector3(w * buildingFootprint, 10, h * buildingFootprint);
Vector3 rot = new Vector3(0, randomY, 0); // set the random Y rotation to a new Vector3
Vector3 scale = Vector3.one; // create a new Vector3 for scale
if(scaleUniform) // scale the object uniformly
{
float randomScale = Random.Range(min, max);
scale = new Vector3(randomScale, randomScale, randomScale);
}
else // or scale it randomly on every axis
{
scale = new Vector3(Random.Range(min, max), Random.Range(min, max), Random.Range(min, max));
}
int index = 0; // declare index here so you dont repeat yourself in ifs
if (result < 5) // now you only set index value instead of copying and pasting long code in each if else
index = 0;
else if (result < 10)
index = 5;
else if (result < 15)
index = 6;
else if (result < 20)
index = 1;
else if (result < 30)
index = 2;
else if (result < 40)
index = 3;
else if (result < 50)
index = 4;
GameObject spawnedBuilding = Instantiate(buildings[index], pos, Quaternion.Euler(rot)); // and finally instantiate the object
spawnedBuilding.transform.localScale = scale; // and set its rotation
}
}
}
Upvotes: 1