# How can I make the y extent height also to be random when instantiate new objects?

With the script I instantiate random objects above the terrain. But the random was only on x and z. Now I want the height of the objects to be random as well.

The terrain position is: X = -250, Y = 0, Z = -250.

So I changed the line:

var y = Extents.y;


To:

var y = Random.Range(-Extents.y, Extents.y);


But now half of the objects above the terrain and half below the terrain, and I want them all to be above the terrain; thus the random height should be above the terrain.

My full code for reference:

using System;
using UnityEngine;
using Random = UnityEngine.Random;

[ExecuteInEditMode]
public class SphereBuilder : MonoBehaviour
{
// for tracking properties change
private Vector3 _extents;
private int _sphereCount;
private float _sphereSize;

/// <summary>
///     How far to place spheres randomly.
/// </summary>
public Vector3 Extents;

/// <summary>
///     How many spheres wanted.
/// </summary>
public int SphereCount;

public float SphereSize;

private GameObject parent;

private void Start()
{
parent = GameObject.Find("Target Builder");
}

private void OnValidate()
{
// prevent wrong values to be entered
Extents = new Vector3(Mathf.Max(0.0f, Extents.x), Mathf.Max(0.0f, Extents.y), Mathf.Max(0.0f, Extents.z));
SphereCount = Mathf.Max(0, SphereCount);
SphereSize = Mathf.Max(0.0f, SphereSize);
}

private void Reset()
{
Extents = new Vector3(250.0f, 20.0f, 250.0f);
SphereCount = 100;
SphereSize = 20.0f;
}

private void Update()
{
}

{
if (Extents == _extents && SphereCount == _sphereCount && Mathf.Approximately(SphereSize, _sphereSize))
return;

// cleanup
var spheres = GameObject.FindGameObjectsWithTag("Target");
foreach (var t in spheres)
{
if (Application.isEditor)
{
DestroyImmediate(t);
}
else
{
Destroy(t);
}
}

var withTag = GameObject.FindWithTag("Terrain");
if (withTag == null)

for (var i = 0; i < SphereCount; i++)
{
var o = GameObject.CreatePrimitive(PrimitiveType.Sphere);
o.tag = "Target";
o.transform.localScale = new Vector3(SphereSize, SphereSize, SphereSize);
o.transform.parent = parent.transform;

// get random position
var x = Random.Range(-Extents.x, Extents.x);
//var y = Extents.y; // sphere altitude relative to terrain below
var y = Random.Range(-Extents.y, Extents.y);
var z = Random.Range(-Extents.z, Extents.z);

// now send a ray down terrain to adjust Y according terrain below
var height = 10000.0f; // should be higher than highest terrain altitude
var origin = new Vector3(x, height, z);
var ray = new Ray(origin, Vector3.down);
RaycastHit hit;
var maxDistance = 20000.0f;
var layerMask = 1 << nameToLayer;
if (Physics.Raycast(ray, out hit, maxDistance, layerMask))
{
var distance = hit.distance;
y = height - distance + y; // adjust
}
else
{
Debug.LogWarning("Terrain not hit, using default height !");
}

// place !
o.transform.position = new Vector3(x, y, z);
}

_extents = Extents;
_sphereCount = SphereCount;
_sphereSize = SphereSize;
}
}


If terrain is at y = 0, you can make sure that the random y value you need is never smaller than zero by writing it like this:

var y = Random.Range(0, 2*Extents.y);


Although the range of values will be as wide as the previous ones, if a primitive gets a y value of 0 it will be split into two halves by the plane:

That's because the primitive origin is its geometric center. So, if we "push" the primitive upwards enough to let it out of being stuck in the plane, it will be just standing onto it:

If you're using spheres as primitives, and you know their radius is r, then you can improve the code like this:

var y = Random.Range(r, 2*Extents.y);


That means the minimum value will be the radius r of the sphere, making the sphere standing on the floor. I guess your radius value is stored by the variable SphereSize, so:

var y = Random.Range(SphereSize, 2*Extents.y);

• It's working fine when I generate 10 or 100 objects but when I changed the Sphere Count for 1000 for testing some of the spheres half under the terrain. Maybe I'm wrong but it looks like that. Here is a link for a screenshot: imgur.com/a/vgbVrfO Jun 4, 2018 at 16:17
• Oh snap, of course this happens! I updated my answer, you shall solve your problem now :) Jun 4, 2018 at 17:46