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

108 lines
2.8 KiB
C#
Raw Normal View History

2024-03-18 18:20:23 +08:00
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using Quadtree;
using UnityEngine;
namespace BITKit.OpenWorld
{
public class WorldChunkService<T> : MonoBehaviour
where T : WorldChunkService<T>
{
public static T Singleton { get; private set; }
private readonly ConcurrentQueue<IWorldChunkObject> _registerQueue = new();
private readonly ConcurrentQueue<IWorldChunkObject> _unregisterQueue = new();
public void Register(IWorldChunkObject obj) => _registerQueue.Enqueue(obj);
public void Unregister(IWorldChunkObject obj) => _unregisterQueue.Enqueue(obj);
2024-03-22 20:16:32 +08:00
protected QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> _quadtree;
private readonly ConcurrentDictionary<int, IWorldChunkObject> dictionary=new();
2024-03-18 18:20:23 +08:00
[SerializeReference, SubclassSelector] private ITicker ticker;
[SerializeField, ReadOnly] private int count;
2024-03-22 20:16:32 +08:00
[SerializeField] private bool drawBounds;
[SerializeField, Range(0, 1024)] private int[] lodDistances;
2024-03-18 18:20:23 +08:00
[SerializeField] private Vector3 size;
private Camera _camera;
private readonly HashSet<int> cacheList = new();
2024-03-22 20:16:32 +08:00
protected virtual void Awake()
2024-03-18 18:20:23 +08:00
{
Singleton = (T) this;
}
2024-03-22 20:16:32 +08:00
protected virtual void Start()
2024-03-18 18:20:23 +08:00
{
ticker.Add(OnTick);
destroyCancellationToken.Register(Dispose);
2024-03-22 20:16:32 +08:00
_quadtree = new QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>>(transform.position, size);
2024-03-18 18:20:23 +08:00
_camera = Camera.main;
}
private void Dispose()
{
ticker.Remove(OnTick);
_registerQueue.Clear();
_unregisterQueue.Clear();
}
2024-03-22 20:16:32 +08:00
protected virtual void OnTick(float deltaTime)
2024-03-18 18:20:23 +08:00
{
while (_unregisterQueue.TryDequeue(out var obj))
{
_quadtree.Remove(obj);
2024-03-22 20:16:32 +08:00
dictionary.Remove(obj.Id, out _);
2024-03-18 18:20:23 +08:00
}
while (_registerQueue.TryDequeue(out var obj))
{
obj.Id = count++;
_quadtree.Insert(obj);
2024-03-22 20:16:32 +08:00
dictionary.TryAdd(obj.Id, obj);
2024-03-18 18:20:23 +08:00
}
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);
2024-03-22 20:16:32 +08:00
var lod = chunkObject.Lod;
if (lod == index) continue;
try
{
chunkObject.Lod = index;
}
catch (Exception e)
{
BIT4Log.LogException(e);
}
2024-03-18 18:20:23 +08:00
}
}
2024-03-22 20:16:32 +08:00
2024-03-18 18:20:23 +08:00
cacheList.Clear();
}
private void OnDrawGizmosSelected()
{
var pos = transform.position;
2024-03-22 20:16:32 +08:00
Gizmos.DrawWireCube(pos,transform.rotation * size);
if(drawBounds)
_quadtree.CurrentRootNode.DrawBounds(true);
if(!_camera)return;
var cameraPosition = _camera.transform.position;
foreach (var VARIABLE in lodDistances)
{
Gizmos.DrawWireSphere(cameraPosition, VARIABLE);
}
2024-03-18 18:20:23 +08:00
}
}
}