using System.Collections; using System.Collections.Generic; using UnityEngine; [ExecuteAlways] public class Lorax : MonoBehaviour { public Terrain Terrain; [Header("Generic Gen")] public int Seed; public bool Regen = false; public bool ShowInEditor = true; public List SpawnableTrees; public List Chances; [Header("Generation Details")] public float HeightMin = 7.5f; public float HeightMax = 9; public float TreeChance = 0.9f; public float CampSize = 10f; public Vector3 CampMiddle; public float RandomNudge = 2f; public float Denseness = 4; public float MinimumAdjacency = 1.5f; private int LastSeed = -1; private Vector3[][] TreePositions; private bool Generated = false; private int ChunkSize = 20; private GameObject[] Chunks; void Start() { Generate(); } void Update() { if (!Application.isPlaying) { if (!ShowInEditor) { if (Generated) { DestroyGenerated(); } return; } if (Generated && LastSeed == Seed && !Regen) { return; } Regen = false; LastSeed = Seed; DestroyGenerated(); Generate(); } } public GameObject GetChunkAt(float x, float y) { int CurrentChunk = (int)((Mathf.Floor((y + 250f) / ChunkSize) * 25f) + Mathf.Floor((x + 250f) / ChunkSize)); return Chunks[CurrentChunk]; } public void DestroyGenerated() { for (int x = transform.childCount - 1; x >= 0; x--) { DestroyImmediate(transform.GetChild(0).gameObject); } Chunks = new GameObject[(500 / ChunkSize) * (500 / ChunkSize)]; Generated = false; } public void Generate() { Random.InitState(Seed); Generated = true; Chunks = new GameObject[(500 / ChunkSize) * (500 / ChunkSize)]; int[] TotalChances = new int[SpawnableTrees.Count + 1]; int Counter = 0; for (int x = 0; x < TotalChances.Length - 1; x++) { TotalChances[x + 1] = Counter + Chances[x]; Counter = TotalChances[x + 1]; } int cap = (int)Mathf.Floor(500 / Denseness); TreePositions = new Vector3[cap][]; for (int y = 0; y < cap; y++) { TreePositions[y] = new Vector3[cap]; for (int x = 0; x < cap; x++) { int CurrentChunk = (int)((Mathf.Floor(y * Denseness / ChunkSize) * 25) + Mathf.Floor(x * Denseness / ChunkSize)); if (Chunks[CurrentChunk] == null) { Chunks[CurrentChunk] = new GameObject("Chunk " + CurrentChunk); Chunks[CurrentChunk].transform.parent = transform; if (Application.isPlaying) { Chunks[CurrentChunk].SetActive(false); } } if (Random.value > TreeChance) { continue; } var pos = new Vector3(x * Denseness - 250 + Random.value * RandomNudge - RandomNudge / 2, 0, y * Denseness - 250 + Random.value * RandomNudge - RandomNudge / 2); TreePositions[y][x] = pos; if (x > 0 && (TreePositions[y][x - 1] - pos).magnitude < MinimumAdjacency) { continue; } if (y > 0 && (TreePositions[y - 1][x] - pos).magnitude < MinimumAdjacency) { continue; } if ((pos - CampMiddle).magnitude < CampSize) { continue; } var height = Terrain.SampleHeight(pos); if (height >= HeightMin && height <= HeightMax) { pos.y = Terrain.transform.position.y + height; var rand = Random.Range(0, TotalChances[TotalChances.Length - 1]); var Chosen = SpawnableTrees[0]; for (int curr = TotalChances.Length - 2; curr > 0; curr--) { if (rand > TotalChances[curr]) { Chosen = SpawnableTrees[curr]; break; } } var rot = Quaternion.Euler(0, 360 * Random.value, 0); var obj = GameObject.Instantiate(Chosen, pos, rot, Chunks[CurrentChunk].transform); } } } } }