using System.Collections; using System.Collections.Generic; using UnityEngine; using Sirenix.OdinInspector; using KairoEngine.Chunks; namespace KairoEngine.TerrainEngine { #if UNITY_EDITOR [UnityEditor.InitializeOnLoad] #endif [HideMonoScript] public class ChunkTerrainCullingSystem : MonoBehaviour { public ChunkTerrainGenerator chunkTerrainGenerator; public int maxChunks = 512; public float destroyDistanceModifier = 3f; public List targets; private void Start() { chunkTerrainGenerator.DestroyTerrain(); chunkTerrainGenerator.Initialize(); for (int i = 0; i < targets.Count; i++) targets[i].lastPosition = new Vector3(); } private void Update() { CullChunks(); } [ShowInInspector] private bool cullObjectsInEditor = false; [Button("Cull Chunks")] private void EditorCulling() { cullObjectsInEditor = !cullObjectsInEditor; if(cullObjectsInEditor) { chunkTerrainGenerator.DestroyTerrain(); chunkTerrainGenerator.Initialize(); UnityEditor.EditorApplication.update += CullChunks; for (int i = 0; i < targets.Count; i++) targets[i].lastPosition = new Vector3(); CullChunks(); } else UnityEditor.EditorApplication.update -= CullChunks; } public void CullChunks() { if(chunkTerrainGenerator == null) return; if(!chunkTerrainGenerator.IsInitialized()) return; for (int i = 0; i < targets.Count; i++) { Vector3 chunkPos = chunkTerrainGenerator.chunkSystem.GetChunkGlobalPositionFromGlobalPosition(targets[i].target.position); if(!chunkPos.Equals(targets[i].lastPosition)) { chunkTerrainGenerator.ClearChunkDataBuffer(); targets[i].chunkPositions.Clear(); targets[i].chunkPositions.InsertRange(0, GetChunkPositions(targets[i].radius, chunkPos)); for (int a = 0; a < targets[i].chunkPositions.Count; a++) { chunkTerrainGenerator.GenerateChunk(targets[i].chunkPositions[a]); } } targets[i].lastPosition = chunkPos; } DestroyChunks(); #if UNITY_EDITOR chunkTerrainGenerator.UpdateEditor (); #endif } private List GetChunkPositions(int radius, Vector3 origin) { List points = new List(); for (int i = 1; i < radius; i++) { for (int j = 1; j < radius; j++) { if (i * i + j * j < (radius * radius)) { points.Add(new Vector2Int(i,j)); points.Add(new Vector2Int(-i,j)); points.Add(new Vector2Int(i,-j)); points.Add(new Vector2Int(-i,-j)); points.Add(new Vector2Int(i, 0)); points.Add(new Vector2Int(-i, 0)); points.Add(new Vector2Int(0, j)); points.Add(new Vector2Int(0, -j)); } } } //Debug.Log($"Found {points.Count} points"); List chunkPositions = new List(); chunkPositions.Add(origin); var voxelSize = chunkTerrainGenerator.voxelSize; var chunkSize = chunkTerrainGenerator.chunkSize; for (int i = 0; i < points.Count; i++) { for (int j = 0; j < chunkTerrainGenerator.chunkLimit.y; j++) { Vector3 pos = new Vector3(points[i].x * chunkSize.x * voxelSize.x, j * chunkSize.y * voxelSize.y, points[i].y * chunkSize.z * voxelSize.z); pos += origin; chunkPositions.Add(pos); } } //Debug.Log($"Found {chunkPositions.Count} chunk positions"); return chunkPositions; } public void DestroyChunks() { int chunkCount = chunkTerrainGenerator.chunkSystem.chunkList.Count; if(chunkCount < maxChunks) return; int destroyCount = chunkCount - maxChunks; Vector3 chunkSize = chunkTerrainGenerator.chunkSize; Vector3 voxelSize = chunkTerrainGenerator.voxelSize; Vector3 size = new Vector3(chunkSize.x * voxelSize.x, chunkSize.y * voxelSize.y, chunkSize.z * voxelSize.z); List destroyList = new List(); for (int i = 0; i < chunkCount; i++) { Vector3 chunkPos = chunkTerrainGenerator.chunkSystem.chunkList[i]; List values = new List(); for (int a = 0; a < targets.Count; a++) { Vector3 targetPos = targets[a].target.position; Vector3 pos = targetPos + (size * targets[a].radius * destroyDistanceModifier); pos.y = targetPos.y; if(Vector3.Distance(targetPos, chunkPos) > Vector3.Distance(targetPos, pos)) values.Add(true); } if(values.Count == targets.Count) destroyList.Add(chunkPos); if(destroyList.Count >= destroyCount) break; } for (int i = 0; i < destroyList.Count; i++) { chunkTerrainGenerator.DestroyChunk(destroyList[i]); } } [System.Serializable] public class CullingTarget { [HorizontalGroup("Target", 0.8f), HideLabel] public Transform target; [HorizontalGroup("Target"), HideLabel, Range(0, 16)] public int radius; public Vector3 lastPosition; public List chunkPositions; } } }