- Home /
How would I instantiate objects on a mesh?
Hi,
I have a mesh (terrain), and I want to instantiate objects (trees) on it. Unfortunately, my knowledge of C# limits me. :(
I've heard of using raycasts, if this is the solution, how would I go about doing that?
Answer by zach-r-d · Jul 02, 2015 at 04:58 AM
For a terrain mesh, the easiest way is to pick a random point in the XZ plane of the terrain (accessible through Renderer.bounds) and do a raycast straight downwards starting from just above the highest point in the terrain (also accessible through Renderer.bounds).
For example, to get a random point on the terrain on which a tree could be spawned, it would look something like this:
Renderer r = GetComponent<Renderer>(); // assumes the terrain is in a mesh renderer on the same GameObject
float randomX = Random.Range(r.bounds.min.x, r.bounds.max.x);
float randomZ = Random.Range(r.bounds.min.z, r.bounds.max.z);
RaycastHit hit;
if (Physics.Raycast(new Vector3(randomX, r.bounds.max.y + 5f, randomZ), -Vector3.up, out hit)) {
// the raycast hit, the point on the terrain is hit.point, spawn a tree there
} else {
// the raycast didn't hit, maybe there's a hole in the terrain?
}
Thank you for your answer! I do have a problem though, no errors or warnings are popping up, but the objects don't seem to instantiate. Here's my code:
using UnityEngine;
using System.Collections;
public class SurfacePopulator : $$anonymous$$onoBehaviour {
public int numberOfObjects;
public int currentObjects;
public GameObject objectToPlace;
private float randomX;
private float randomZ;
private Renderer r;
void Start() {
r = GetComponent<Renderer>();
randomX = Random.Range(r.bounds.$$anonymous$$.x, r.bounds.max.x);
randomZ = Random.Range(r.bounds.$$anonymous$$.z, r.bounds.max.z);
}
void Update() {
RaycastHit hit;
if(currentObjects <= numberOfObjects) {
if (Physics.Raycast(new Vector3(randomX, r.bounds.max.y + 5f, randomZ), -Vector3.up, out hit)) {
Instantiate(objectToPlace, hit.point, Quaternion.identity);
currentObjects += 1;
}
}
}
}
I've traced the problem to this line:
if (Physics.Raycast(new Vector3(randomX, r.bounds.max.y + 5f, randomZ), -Vector3.up, out hit)) {
The first if statement is passed, but the second one isn't.
Hey! I saw your post and decided to ask you about the code you've used. I am a complete newbie to Unity. $$anonymous$$y problem is that I have series of meshes representing a map (2D), and I need to create instances of Image Gameobject inside the mesh with randomised locations over each of the mesh layers. The problem is that when I tried to use the code which you have posted it did not show anything, could be some advice on this matter? I would really appreciate your support!
Ah, thanks for tracing the problem. First, move the assignments to randomX and randomZ between the two if statements; otherwise the ray will fire from the same point every time and the trees will form a single column. Second, make sure the terrain has a collider on it; raycasts can only hit things with colliders.
yo wth thanks dude i've been looking for a lot of time for something similar not knowing how to phrase it. you saved me a lot of time! thanks!
Answer by Sawula · Feb 15, 2017 at 03:14 PM
A bit old I know, but this is very close to what I'm doing, except sometime when I instantiate my object, they spawn halfway into the mesh instead of on its surface. Is there any way to avoid this?