Reputation: 507
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Teleport : MonoBehaviour {
public Vector3 terrainArea;
public float spinSpeed = 2.0f;
public int cloneTeleportations;
public GameObject prefab;
private bool rotate = false;
private bool exited = false;
private Transform[] teleportations;
private Random rnd = new Random();
private void Start()
{
GameObject go = GameObject.Find("Terrain");
Terrain terrain = go.GetComponent(Terrain);
terrainArea = terrain.terrainData.size;
for (int i = 0; i < cloneTeleportations; i++)
{
GameObject Teleportaion = Instantiate(prefab, new Vector3(Random.Range(i * 10.0F, i * 50.0F), 0, Random.Range(i * 10.0F, i * 50.0F)), Quaternion.identity);
Teleportaion.transform.parent = this.transform;
Teleportaion.transform.tag = "Teleportation";
}
}
}
Now some gameobjects are out of the terrain area. What I want to do is to keep the clones to be in random position but only inside the terrain area.
How I do Instantiate Objects inside the terrain area?
Upvotes: 0
Views: 5069
Reputation: 125455
I noticed that you are creating new instance of the Random
class. Don't do that with Unity's Random
API. Just use Random.Range
to generate random numbers.
As for generating random GameObjects on a terrain:
1.Find the X position:
Min = terrain.terrainData.size.x.
Max = terrain.transform.position.x + terrain.terrainData.size.x.
The final random X should be:
randX = UnityEngine.Random.Range(Min, Min + Max);
2.Find the Z position:
Min = terrain.transform.position.z;
Max = terrain.transform.position.z + terrain.terrainData.size.z;
The final random Z should be:
randZ = UnityEngine.Random.Range(Min, Min + Max);
3.Find the Y position:
The y-axis does not have to be random. Although, you can make it a random value if you want.
It just has to be over the terrain so that the Instantiated Object will not be under the terrain.
This is where Terrain.SampleHeight
comes into place. You must use this function in order to perfectly generate a position that is not under the terrain. You need the result from #1 and #2 to use this:
yVal = Terrain.activeTerrain.SampleHeight(new Vector3(randX, 0, randZ));
If you want to apply offset to the y-axis, you can now do it at this time.
yVal = yVal + yOffset;
Below is a general example. You have to use this example to extend your current code.
public GameObject prefab;
public Terrain terrain;
public float yOffset = 0.5f;
private float terrainWidth;
private float terrainLength;
private float xTerrainPos;
private float zTerrainPos;
void Start()
{
//Get terrain size
terrainWidth = terrain.terrainData.size.x;
terrainLength = terrain.terrainData.size.z;
//Get terrain position
xTerrainPos = terrain.transform.position.x;
zTerrainPos = terrain.transform.position.z;
generateObjectOnTerrain();
}
void generateObjectOnTerrain()
{
//Generate random x,z,y position on the terrain
float randX = UnityEngine.Random.Range(xTerrainPos, xTerrainPos + terrainWidth);
float randZ = UnityEngine.Random.Range(zTerrainPos, zTerrainPos + terrainLength);
float yVal = Terrain.activeTerrain.SampleHeight(new Vector3(randX, 0, randZ));
//Apply Offset if needed
yVal = yVal + yOffset;
//Generate the Prefab on the generated position
GameObject objInstance = (GameObject)Instantiate(prefab, new Vector3(randX, yVal, randZ), Quaternion.identity);
}
Upvotes: 2