Instantiate objects within the terrain area

Solution 1:

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);
}