1
This commit is contained in:
@@ -8,7 +8,8 @@
|
||||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23"
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:045a42f233e479d41adc32d02b99631e"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
@@ -13,7 +13,8 @@ namespace BITKit.OpenWorld
|
||||
[SerializeField,ReadOnly] private int id;
|
||||
[SerializeField] protected Vector3 size = Vector3.one;
|
||||
[SerializeField] protected Vector3 offset = Vector3.one * 0.5f;
|
||||
public Bounds GetBounds()=>new Bounds(transform.position+transform.rotation * offset,transform.rotation * size);
|
||||
public Bounds GetBounds() => _bounds;
|
||||
private Bounds _bounds;
|
||||
public Node<IWorldChunkObject> ParentNode { get; set; }
|
||||
public void QuadTree_Root_Initialized(IQuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> root)
|
||||
{
|
||||
@@ -30,6 +31,7 @@ namespace BITKit.OpenWorld
|
||||
}
|
||||
protected virtual void Start()
|
||||
{
|
||||
_bounds= new Bounds(transform.position+transform.rotation * offset,transform.rotation * size);
|
||||
UnityWorldChunkService.Singleton.Register(this);
|
||||
destroyCancellationToken.Register(Dispose);
|
||||
}
|
||||
|
@@ -18,8 +18,17 @@ namespace BITKit.OpenWorld
|
||||
[SerializeField] private ChunkBehaviour chunkBehaviour;
|
||||
private void Start()
|
||||
{
|
||||
chunkBehaviour.OnLodChangedEvent += OnLodChanged;
|
||||
if(colliders is {Length:0})colliders = GetComponentsInChildren<Collider>();
|
||||
try
|
||||
{
|
||||
chunkBehaviour.OnLodChangedEvent += OnLodChanged;
|
||||
if(colliders is {Length:0})colliders = GetComponentsInChildren<Collider>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.Warning<ColliderChunkObject>(gameObject.name);
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
|
||||
}
|
||||
private void OnLodChanged(int arg1, int arg2)
|
||||
{
|
||||
@@ -30,22 +39,28 @@ namespace BITKit.OpenWorld
|
||||
{
|
||||
x.enabled = enabledCollider;
|
||||
}
|
||||
catch (UnassignedReferenceException)
|
||||
{
|
||||
GetCollidersInChildren();
|
||||
OnLodChanged(arg1, arg2);
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.Warning<ColliderChunkObject>(gameObject.name);
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
[BIT]
|
||||
private void GetCollidersInChildren()
|
||||
{
|
||||
colliders = GetComponentsInChildren<Collider>();
|
||||
#if UNITY_EDITOR
|
||||
EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -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()
|
||||
|
@@ -25,7 +25,7 @@ namespace BITKit.OpenWorld
|
||||
if (_sceneHandle is not null) return;
|
||||
var stopWatcher = new System.Diagnostics.Stopwatch();
|
||||
stopWatcher.Start();
|
||||
_sceneHandle = YooAssets.LoadSceneAsync(sceneName.Value,LoadSceneMode.Additive,suspendLoad:true,priority:8);
|
||||
_sceneHandle = YooAssets.LoadSceneAsync(sceneName.Value,LoadSceneMode.Additive,priority:8);
|
||||
await _sceneHandle;
|
||||
stopWatcher.Stop();
|
||||
Debug.Log($"加载场景 {sceneName.Value} 耗时 {stopWatcher.ElapsedMilliseconds}ms");
|
||||
|
Reference in New Issue
Block a user