Not the terrain but inside a rectangle area i built with another script. Rectangle of cubes.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RandomSpawnObjects : MonoBehaviour
{
public Terrain terrain;
public GameObject[] prefabs;
public int prefabsNumber;
public int positionArea;
public int gap = 3;
// Use this for initialization
void Start ()
{
var walls = GetComponent<Walls>();
var spawnArea = walls.wallsSize;
prefabsNumber = Random.Range(5, 30);
positionArea = Random.Range(3, 30);
for (int i = 0; i < prefabsNumber; i++)
{
Instantiate(prefabs_, prefabs*.transform.position, Quaternion.identity);*_
} * }*
* // Update is called once per frame* * void Update ()* {
* }* }
walls.wallsSize give me the size for example 100 so the area will be 100*100 like 100 width and 100 height. But not sure how to get it calculate the area from walls.wallsSize Then what i want to do is to Instantiate random number of prefabs in random positions within the walls size area and gap/space between the prefabs of 10 for example and if a prefab is randomly Instantiated near one of the walls also keep gap of 10 from the wall/s Also making each prefab a random rotation angle is good option.
So you have to spawn your assets randomly inside the rectangle. First you have to determine the minX, axX, minY and maxY of your rectangle. Then when a simple Instantiate function, you spawn them randomly inside these coordinates.
Instantiate(*your object*, new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY)), *your quaternion*);
that way the instatiated prefabs will be in the rectangle, or at least the pivot of the prefabs.
To have a random rotation, just use Quaternion.Euler(0.0, 0.0, Random.Range(0.0, 360.0) as a quaternion if of course it’s the z value that you want to randomize. Saw in this topic.
And now if you want your instantiated prefabs to have a gap of 10 between each, then use an random integer and multiply it by 10
int randomIntX = Random.Range (Mathf.RoundToInt(minX/10), Mathf.RoundToInt(maxX/10));
int randomIntY = Random.Range (Mathf.RoundToInt(minY/10), Mathf.RoundToInt(maxY/10));
Instantiate(*your object*, new Vector2(randomIntX, randomIntY) * 10, *your quaternion*);
There are two parts to your question. I will try to answer them after another.
1. How do you ensure that the obstacle spawning is done after the wall generation?
This can be done by writing a coordinating MonoBehavior, SpawnSequence. SpawnSequence will hold a reference to your wall generator and your obstacle generator. The generators will no longer use the Start method to start doing their stuff. Instead, SpawnSequence will call the spawning functions in the order you choose.
A bare-bones example would look something like this:
public class SpawnSequence : MonoBehaviour
{
public EnvironmentSpawner environmentSpawner;
public ObstacleSpawner obstacleSpawner;
public void Start()
{
environmentSpawner.SpawnEnvironment();
obstacleSpawner.SpawnObstacles(environmentSpawner.GetEnvironmentBounds());
}
}
public class EnvironmentSpawner : MonoBehaviour
{
public Vector3 spawnAreaSize;
public void SpawnEnvironment()
{
// Spawn the walls here
}
public Bounds GetEnvironmentBounds()
{
return new Bounds(transform.position, spawnAreaSize);
}
}
public class ObstacleSpawner : MonoBehaviour
{
public void SpawnObstacles(Bounds bounds)
{
}
}
2. How do you ensure that the obstacles are at least 10m apart?
In your comments above you posted a function isSpaceClear that casts a sphere at the candidate point and checks for overlaps. This ensures that the distance between the candidate point and any collider is not smaller than the desired gap (red line in the diagram).
However, you want to calculate the closest distance between two colliders (the purple line in the diagram above). This is not impossible, but might require some thought, as there are many types of colliders and each combination might need a unique way of calculating the distance between them.
This can be mitigated by making some assumptions. For example, you could assume that your obstacles may only contain one Collider and that it may only be of one type (for example BoxCollider would probably work fine as a start).
Then, spawning the obstacles one after another and checking the distance condition after each is the right way to do it. However, you have to keep in mind that it might not be possible to spawn the desired amount of obstacles in a given space. By specifying a spawn area of size 0, for example, no obstacle will be able to be spawned. This will result in an infinite loop, freezing Unity.
I would suggest keeping track of the number of times you retried a spawn iteration and just giving up entirely after maybe a thousand retries or so.