Hello everyone.
My name is Julien ? I’m a small 2.8k youtuber leader of my old project named “No Braves”. Since a yesterday I am trying to create a procedural Infinte world generation and for my new game and for the moment everything goes pretty well except that I can’t figure out how to add grass to my mesh. My world is generated using procedurally generated meshs of different lefvels of details. I created my terrain based on 3 “layers”, the ground layer, a hills layer and a mountains layer. The texture on top of my terrain is entierly managed by my custom shader (wich is very primitive for the moment because there is no blending).
So I really an’t figure out how to add grass to such a world. I tried different technique with grass GameObjects, Planes etc but they all not worked… If someone can help me it could be awsome!
I can explain you how I manage my vegetation script. I call the GenerateVegetation function on the chunk load and I just randomly place the trees on top of the terrain using a raycasting to get the point and the normal (I check the slope with the y axis of the vertex’s norma).
Here is my vegetation script (very basic for the moment I just done it now)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VegetationGeneration {
public static IEnumerator Generate(Vector2 chunk) {
// setting up the Vegetation holder child of the global chunk (hierachy);
Transform vegetationChunk = new GameObject ("Vegetation").transform;
vegetationChunk.parent = GameSettings.chunks [chunk];
// Get all the vegetation instances and loop start iterating the placement
foreach(Vegetation vegetation in MapPreview.instance.vegetation) {
float amount = Random.Range (vegetation.amount.x, vegetation.amount.y);
for(int i = 0; i < amount; i++) {
// Splitting the generation calculations each 15 trees (Only while playtime) (Performance)
if (!Application.isEditor && i % 15 == 0) yield return null;
// Getting a random position in the chunk
float chunkDiameter = GameSettings.worldChunkSize / 2f;
Vector3 position = new Vector3 (Random.Range (-chunkDiameter, chunkDiameter), 0f, Random.Range (-chunkDiameter, chunkDiameter)) + new Vector3(chunk.x, 0f, chunk.y);
// Shooting a raycast down to get the hit point and hit normal
// Check the slope angle
RaycastHit hit;
float slope;
if(Physics.Raycast(new Ray(position + Vector3.up * 100f, Vector3.down), out hit, 200f, MapPreview.instance.groundLayer) && (slope = hit.normal.y) > vegetation.maxSlope) {
// possible to spawn the vegetation at the given point
// Spawning the entity with the vegetation chunk parent
GameObject prefab = vegetation.vegetation [Random.Range (0, vegetation.vegetation.Length)];
GameObject entity = GameObject.Instantiate (prefab, vegetationChunk);
// setting parameters
entity.transform.position = hit.point;
entity.transform.localEulerAngles += new Vector3 (0f, Random.Range (0f, 360f), 0f);
// Getting a random scale and converting it to a uniform vector
float scale = Random.Range (vegetation.scale.x, vegetation.scale.y);
entity.transform.localScale = Vector3.one * scale;
// Putting the vegetation into the ground to avoit flying trees
entity.transform.position -= Vector3.up * vegetation.depth.Evaluate (slope);
// Set to a different layre than the ground to avoid trees over other trees (Raycasting)
SetLayer (entity.transform);
}
}
}
}
// A simple Recusrive function that will loop thru every child of the root
// TRansform and apply the right layer to it
static void SetLayer(Transform parent) {
parent.gameObject.layer = LayerMask.NameToLayer (MapPreview.instance.vegetationLayer);
foreach(Transform child in parent) SetLayer (child);
}
}
// Vegetation Object
[System.Serializable]
public class Vegetation {
public string name;
[Tooltip("Amount of vegetation per generated chunk (does not represent the real amount because they won't be placed if the place is not survivable)")]
public Vector2 amount = new Vector2(50,70);
public GameObject[] vegetation;
public Vector2 scale;
[Range(0f,1f)]
public float maxSlope = 0.7f;
public AnimationCurve depth = new AnimationCurve(new Keyframe[] { new Keyframe(0f, 0.05f), new Keyframe(1f, 0.25f) });
}
If someone has the clue, please answer this topic, I think I am not the only one that looks for this question ;D
Thank you really much to you guys for readin this question !
Best regards,
Julien.