Random/Procedural Object spawner?

Hi… im trying to basically fill this plane with grass/trees/brush and other things… I’ve been looking up tutorials online and most of them have been on creating large worlds… and not dealing with just objects… I’m not sure if I use a texture or really how to go about this… any help would be amazing!!

Hi @Rosscoe3,

Depending on time constraints and budget you may benefit from buying something like MegaScatter:

Otherwise here’s some ideas that’ll hopefully point you in the right direction!

Research voxels:

To start add a material/texture to the plane with a normal map to create the illusion of a 3D grass (once you start placing objects on top it’ll become less noticeable).

Create the assets you want to use and make a script to attach to all of them. This script can then use Foreach to add them to a List(), from there you can use random number generators (or seeds) to decide what gets instantiated. It’s too far a complex topic for an answer here but I’ll attach an extract from a script I use for some boids (NOTE: it is an extract and won’t work if you copy it directly into your project). It’s not quite the same but it’s similar enough to give you a launching point for going forward!

As for terrain perlin noise is a fairly common way to randomly create a heightmap but it has it’s shortfalls too - for example, in it’s “basic” form you won’t generate any caves.

Here’s a link to a fairly interesting read as well on the topic of procedural generation:

Obviously it’s a large topic, open for a lot of discussion, so feel free to ask me anything else.

All the best!

EDIT: Please remember if this has been useful to upvote it :slight_smile:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ProceduralObsBoid : MonoBehaviour 
{
	public static List<ProceduralObsBoid> boids;
	public static ProceduralObsBoid S;

	public List<ProceduralObsBoid> neighbours; 
	public List<ProceduralObsBoid> collisionRisks;
	public ProceduralObsBoid closest; 

	private void Awake()
	{
		if (boids == null) 
		{
			boids = new List<ProceduralObsBoid>();
		}
		boids.Add (this);

		S = this;

		neighbours = new List<ProceduralObsBoid> ();
		collisionRisks = new List<ProceduralObsBoid> ();
	}

	public List<ProceduralObsBoid> GetNeighbours(ProceduralObsBoid boi)
	{
		float closestDist = float.MaxValue;
		Vector3 delta;
		float dist;
		neighbours.Clear();
		collisionRisks.Clear();

		foreach (ProceduralObsBoid b in boids) 
		{
			if (b == boi) continue;
			delta = b.transform.position - boi.transform.position;
			dist = delta.magnitude;
			if (dist < closestDist)
			{
				closestDist = dist;
				closest = b;
			}
			if (dist < ProceduralLevel.S.nearDist)
			{
				neighbours.Add (b);
			}
			if (dist < ProceduralLevel.S.collisionDist)
			{
				collisionRisks.Add (b);
			}
		}
		if (neighbours.Count == 0) 
		{
			neighbours.Add (closest);
		}
		return (neighbours);
	}

	public Vector3 GetAveragePos (List<ProceduralObsBoid> someBoids)
	{
		Vector3 sum = Vector3.zero;
		foreach (ProceduralObsBoid b in someBoids) 
		{
			sum += b.transform.position;
		}
		Vector3 centre = sum / someBoids.Count;
		return (centre);
	}
}