using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using Quadtree; using Quadtree.Items; using UnityEngine; using UnityEngine.Pool; namespace BITKit.OpenWorld { [Serializable] public struct UnityWorldChunkSingleton:IChunkService { public void Register(IWorldChunkObject obj)=>UnityWorldChunkService.Register(obj); public void Unregister(IWorldChunkObject obj)=>UnityWorldChunkService.Unregister(obj); } public class UnityWorldChunkService : MonoBehaviour { [RuntimeInitializeOnLoadMethod] private static void Reload() { _registerQueue.Clear(); _unregisterQueue.Clear(); } private static readonly ConcurrentQueue _registerQueue = new(); private static readonly ConcurrentQueue _unregisterQueue = new(); public static void Register(IWorldChunkObject obj)=>_registerQueue.Enqueue(obj); public static void Unregister(IWorldChunkObject obj)=>_unregisterQueue.Enqueue(obj); private QuadtreeRoot> _quadtree; [SerializeReference, SubclassSelector] private ITicker ticker; [SerializeField,ReadOnly] private int count; [SerializeField,Range(0,128)] private int[] lodDistances; [SerializeField] private Vector3 size; private Camera _camera; private readonly HashSet cacheList = new(); private void Start() { ticker.Add(OnTick); destroyCancellationToken.Register(Dispose); _quadtree = new QuadtreeRoot>(default,size); _camera = Camera.main; } private void Dispose() { ticker.Remove(OnTick); Reload(); } private void OnTick(float deltaTime) { while (_unregisterQueue.TryDequeue(out var obj)) { _quadtree.Remove(obj); } while (_registerQueue.TryDequeue(out var obj)) { obj.Id = count++; _quadtree.Insert(obj); } var cameraPosition = _camera.transform.position; for (var index = 0; index < lodDistances.Length; index++) { var distance = lodDistances[index]; foreach (var chunkObject in _quadtree.Find(new Bounds(cameraPosition, Vector3.one * distance))) { if (cacheList.Contains(chunkObject.Id)) continue; cacheList.Add(chunkObject.Id); var lod = chunkObject.Lod; if (lod == index) continue; chunkObject.Lod = index; } } cacheList.Clear(); } private void OnDrawGizmosSelected() { var pos = transform.position; // pos.x-=size.x/2; // pos.y-=size.y/2; // pos.z-=size.z/2; Gizmos.DrawWireCube(pos, size); } } }