This commit is contained in:
CortexCore
2024-04-16 04:06:46 +08:00
parent 37e7fcea51
commit c798b224be
67 changed files with 1305 additions and 425 deletions

View File

@@ -2,8 +2,11 @@ using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using BITKit.SceneManagement;
using Cysharp.Threading.Tasks;
using Quadtree;
using UnityEngine;
using UnityEngine.Pool;
namespace BITKit.OpenWorld
@@ -21,13 +24,16 @@ namespace BITKit.OpenWorld
private readonly ConcurrentDictionary<int, IWorldChunkObject> dictionary=new();
[SerializeReference, SubclassSelector] private ITicker ticker;
[SerializeReference, SubclassSelector] private ISceneService sceneService;
[SerializeField, ReadOnly] private int count;
[SerializeField, ReadOnly] private int tickTaskCount;
[SerializeField] private bool drawBounds;
[SerializeField, Range(0, 1024)] private int[] lodDistances;
[SerializeField] private Vector3 size;
private Camera _camera;
private readonly HashSet<int> cacheList = new();
private readonly Queue<(int, IWorldChunkObject)> lodQueue=new();
private bool isBusy;
protected virtual void Awake()
{
Singleton = (T) this;
@@ -35,20 +41,35 @@ namespace BITKit.OpenWorld
protected virtual void Start()
{
sceneService?.RegisterLoadTaskAsync(LoadTask);
ticker.Add(OnTick);
destroyCancellationToken.Register(Dispose);
_quadtree = new QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>>(transform.position, size);
_camera = Camera.main;
}
private void Dispose()
private async UniTask LoadTask()
{
var frame=0;
while (count is 0 || frame++<32)
{
if (destroyCancellationToken.IsCancellationRequested) return;
await UniTask.NextFrame();
}
}
protected virtual void Dispose()
{
sceneService?.UnRegisterLoadTaskAsync(LoadTask);
ticker.Remove(OnTick);
_registerQueue.Clear();
_unregisterQueue.Clear();
}
protected virtual void OnTick(float deltaTime)
protected virtual async void OnTick(float deltaTime)
{
if (!enabled) return;
if (isBusy) return;
isBusy = true;
while (_unregisterQueue.TryDequeue(out var obj))
{
_quadtree.Remove(obj);
@@ -63,28 +84,76 @@ namespace BITKit.OpenWorld
}
var cameraPosition = _camera.transform.position;
var cycle = 0;
for (var index = 0; index < lodDistances.Length; index++)
await UniTask.SwitchToThreadPool();
foreach (var chunkObject in _quadtree.Find(new Bounds(cameraPosition, Vector3.one * (lodDistances[^1]+lodDistances[0]))))
{
var distance = lodDistances[index];
foreach (var chunkObject in _quadtree.Find(new Bounds(cameraPosition, Vector3.one * distance)))
if (cycle++ > 64)
{
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);
}
cycle = 0;
await UniTask.NextFrame();
if (destroyCancellationToken.IsCancellationRequested) return;
}
var distance = Vector3.Distance(cameraPosition, chunkObject.GetBounds().center);
//var distance = Vector3.Distance(cameraPosition, chunkObject.GetBounds().ClosestPoint(cameraPosition));
if (cacheList.Contains(chunkObject.Id)) continue;
cacheList.Add(chunkObject.Id);
var lod = -1;
for (var i = 0; i < lodDistances.Length; i++)
{
if (!(distance < lodDistances[i])) continue;
lod = i;
break;
}
if(chunkObject.Lod==lod)continue;
//chunkObject.Lod = lod;
lodQueue.Enqueue((lod,chunkObject));
}
// 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);
// }
// }
// }
await UniTask.SwitchToMainThread();
tickTaskCount = lodQueue.Count;
if (destroyCancellationToken.IsCancellationRequested) return;
cycle = 0;
while (lodQueue.TryDequeue(out var value))
{
if (cycle++ > 8)
{
cycle = 0;
await UniTask.NextFrame();
if (destroyCancellationToken.IsCancellationRequested) return;
}
value.Item2.Lod = value.Item1;
}
isBusy = false;
cacheList.Clear();
}
private void OnDrawGizmosSelected()