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 Destroy = false; 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 int ChunkSize = 20; private GameObject[] Chunks; void Start() { Debug.Log((int)((Mathf.Floor((228.55f) / ChunkSize) * 25) + Mathf.Floor(245.27f / ChunkSize))); } void Update() { if (Application.isEditor) { if (Destroy) { Destroy = false; DestroyGenerated(); } if (LastSeed == Seed && !Regen) { return; } Regen = false; LastSeed = Seed; DestroyGenerated(); Generate(); } } public GameObject GetChunkAt(float x, float y) { /*Debug.Log("----------------"); Debug.Log("y: " + (y + 250f)); Debug.Log("x: " + (x + 250f)); Debug.Log("y divided: " + (y + 250f) / ChunkSize); Debug.Log("x divided: " + (x + 250f) / ChunkSize); Debug.Log("y floored: " + (Mathf.Floor((y + 250f) / ChunkSize))); Debug.Log("x floored: " + (Mathf.Floor((x + 250f) / ChunkSize)));*/ 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)]; } public void Generate() { Random.InitState(Seed); 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; 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); } } } } }