BITFALL/Assets/BITKit/Unity/Scripts/WorldChunk/UnityWorldChunkService.cs

96 lines
2.6 KiB
C#
Raw Normal View History

2024-03-17 02:24:55 +08:00
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<IWorldChunkObject> _registerQueue = new();
private static readonly ConcurrentQueue<IWorldChunkObject> _unregisterQueue = new();
public static void Register(IWorldChunkObject obj)=>_registerQueue.Enqueue(obj);
public static void Unregister(IWorldChunkObject obj)=>_unregisterQueue.Enqueue(obj);
private QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> _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<int> cacheList = new();
private void Start()
{
ticker.Add(OnTick);
destroyCancellationToken.Register(Dispose);
_quadtree = new QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>>(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);
}
}
}