1
This commit is contained in:
107
Src/Unity/Scripts/WorldChunk/WorldChunkService.cs
Normal file
107
Src/Unity/Scripts/WorldChunk/WorldChunkService.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
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);
|
||||
protected QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> _quadtree;
|
||||
private readonly ConcurrentDictionary<int, IWorldChunkObject> dictionary=new();
|
||||
|
||||
[SerializeReference, SubclassSelector] private ITicker ticker;
|
||||
[SerializeField, ReadOnly] private int count;
|
||||
[SerializeField] private bool drawBounds;
|
||||
[SerializeField, Range(0, 1024)] private int[] lodDistances;
|
||||
[SerializeField] private Vector3 size;
|
||||
private Camera _camera;
|
||||
private readonly HashSet<int> cacheList = new();
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Singleton = (T) this;
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
ticker.Add(OnTick);
|
||||
destroyCancellationToken.Register(Dispose);
|
||||
_quadtree = new QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>>(transform.position, size);
|
||||
_camera = Camera.main;
|
||||
}
|
||||
private void Dispose()
|
||||
{
|
||||
ticker.Remove(OnTick);
|
||||
_registerQueue.Clear();
|
||||
_unregisterQueue.Clear();
|
||||
}
|
||||
protected virtual void OnTick(float deltaTime)
|
||||
{
|
||||
while (_unregisterQueue.TryDequeue(out var obj))
|
||||
{
|
||||
_quadtree.Remove(obj);
|
||||
dictionary.Remove(obj.Id, out _);
|
||||
}
|
||||
|
||||
while (_registerQueue.TryDequeue(out var obj))
|
||||
{
|
||||
obj.Id = count++;
|
||||
_quadtree.Insert(obj);
|
||||
dictionary.TryAdd(obj.Id, 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;
|
||||
try
|
||||
{
|
||||
chunkObject.Lod = index;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cacheList.Clear();
|
||||
}
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
var pos = transform.position;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user