1
This commit is contained in:
12
Assets/BITKit/Unity/Scripts/WorldChunk/AIChunkService.cs
Normal file
12
Assets/BITKit/Unity/Scripts/WorldChunk/AIChunkService.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.OpenWorld
|
||||
{
|
||||
public class AIChunkService : WorldChunkService<AIChunkService>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "BITKit.WorkdChunk",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:a9eec99827e569e45bfe3e5ea7494591",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "BITKit.WorldChunk",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:1193c2664d97cc049a6e4c486c6bce71",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:045a42f233e479d41adc32d02b99631e"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
namespace BITKit.OpenWorld
|
||||
{
|
||||
public sealed class BuildingChunkObject : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private ChunkBehaviour chunkBehaviour;
|
||||
[SerializeField] private Renderer[] interiorRenderers;
|
||||
[SerializeField] private Optional<Transform> useRoot;
|
||||
private void Start()
|
||||
{
|
||||
chunkBehaviour.OnLodChangedEvent += OnLodChanged;
|
||||
if(useRoot.Allow is false)return;
|
||||
var renderers = ListPool<Renderer>.Get();
|
||||
renderers.AddRange(interiorRenderers);
|
||||
renderers.AddRange(useRoot.Value.GetComponentsInChildren<Renderer>());
|
||||
interiorRenderers = renderers.Distinct().ToArray();
|
||||
renderers.Clear();
|
||||
ListPool<Renderer>.Release(renderers);
|
||||
}
|
||||
private void OnLodChanged(int oldLod, int newLod)
|
||||
{
|
||||
var show = newLod is 0;
|
||||
foreach (var x in interiorRenderers)
|
||||
{
|
||||
x.enabled = show;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
46
Assets/BITKit/Unity/Scripts/WorldChunk/ChunkBehaviour.cs
Normal file
46
Assets/BITKit/Unity/Scripts/WorldChunk/ChunkBehaviour.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using BITKit.OpenWorld;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
namespace BITKit.OpenWorld
|
||||
{
|
||||
public class ChunkBehaviour : ChunkObject
|
||||
{
|
||||
public event Action<int,int> OnLodChangedEvent;
|
||||
protected override void OnLodChanged(int oldLod, int newLod)
|
||||
{
|
||||
base.OnLodChanged(oldLod, newLod);
|
||||
OnLodChangedEvent?.Invoke(oldLod,newLod);
|
||||
}
|
||||
|
||||
[BIT]
|
||||
private void CalculateBounds()
|
||||
{
|
||||
if(TryGetComponent<Collider>(out var _collider))
|
||||
{
|
||||
var bounds1 = _collider.bounds;
|
||||
size = bounds1.size;
|
||||
offset = bounds1.center - transform.position;
|
||||
|
||||
return;
|
||||
}
|
||||
Bounds bounds = new();
|
||||
foreach (var x in GetComponentsInChildren<Collider>())
|
||||
{
|
||||
bounds.Encapsulate(x.bounds);
|
||||
if (x.bounds.size.sqrMagnitude > 64)
|
||||
{
|
||||
Debug.LogWarning($"{x.gameObject.name}:Size is too large, please check the size of the collider");
|
||||
}
|
||||
}
|
||||
size = bounds.size;
|
||||
offset = bounds.center - transform.position;
|
||||
EditorUtility.SetDirty(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
73
Assets/BITKit/Unity/Scripts/WorldChunk/ChunkLodObject.cs
Normal file
73
Assets/BITKit/Unity/Scripts/WorldChunk/ChunkLodObject.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Quadtree;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.OpenWorld
|
||||
{
|
||||
public class ChunkLodObject : MonoBehaviour, IWorldChunkObject
|
||||
{
|
||||
[Serializable]
|
||||
public struct Data
|
||||
{
|
||||
public Renderer[] renderers;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private Data[] lodObjects;
|
||||
[SerializeField,ReadOnly] private int _lod = -1;
|
||||
[SerializeField,ReadOnly] private int id;
|
||||
[SerializeField] private Vector3 initialSize;
|
||||
private Bounds _bounds;
|
||||
public Bounds GetBounds() => _bounds;
|
||||
public Node<IWorldChunkObject> ParentNode { get; set; }
|
||||
public void QuadTree_Root_Initialized(IQuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> root)
|
||||
{
|
||||
}
|
||||
public int Id
|
||||
{
|
||||
get=>id;
|
||||
set=>id = value;
|
||||
}
|
||||
public int Lod
|
||||
{
|
||||
get=>_lod;
|
||||
set
|
||||
{
|
||||
if (_lod is not -1)
|
||||
{
|
||||
foreach (var x in lodObjects[_lod].renderers)
|
||||
{
|
||||
if(x)x.enabled = false;
|
||||
}
|
||||
}
|
||||
_lod = value;
|
||||
if (_lod is -1) return;
|
||||
if (lodObjects.Length <= _lod) return;
|
||||
foreach (var x in lodObjects[_lod].renderers)
|
||||
{
|
||||
if(x)x.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_bounds = new Bounds(transform.position, initialSize);
|
||||
foreach (var x in lodObjects)
|
||||
foreach (var xx in x.renderers)
|
||||
{
|
||||
xx.enabled = false;
|
||||
}
|
||||
UnityWorldChunkService.Singleton.Register(this);
|
||||
destroyCancellationToken.Register(Dispose);
|
||||
}
|
||||
|
||||
private void Dispose()
|
||||
{
|
||||
UnityWorldChunkService.Singleton.Unregister(this);
|
||||
}
|
||||
}
|
||||
}
|
55
Assets/BITKit/Unity/Scripts/WorldChunk/ChunkObject.cs
Normal file
55
Assets/BITKit/Unity/Scripts/WorldChunk/ChunkObject.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.NetworkInformation;
|
||||
using Quadtree;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.OpenWorld
|
||||
{
|
||||
public class ChunkObject : MonoBehaviour,IWorldChunkObject
|
||||
{
|
||||
[SerializeField,ReadOnly] private int _lod = -1;
|
||||
[SerializeField,ReadOnly] private int id;
|
||||
[SerializeField] protected Vector3 size = Vector3.one;
|
||||
[SerializeField] protected Vector3 offset = Vector3.one * 0.5f;
|
||||
public Bounds GetBounds() => _bounds;
|
||||
private Bounds _bounds;
|
||||
public Node<IWorldChunkObject> ParentNode { get; set; }
|
||||
public void QuadTree_Root_Initialized(IQuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> root)
|
||||
{
|
||||
}
|
||||
public int Id
|
||||
{
|
||||
get=>id;
|
||||
set=>id = value;
|
||||
}
|
||||
public int Lod
|
||||
{
|
||||
get=>_lod;
|
||||
set => OnLodChanged(_lod,_lod=value);
|
||||
}
|
||||
protected virtual void Start()
|
||||
{
|
||||
_bounds= new Bounds(transform.position+transform.rotation * offset,transform.rotation * size);
|
||||
UnityWorldChunkService.Singleton.Register(this);
|
||||
destroyCancellationToken.Register(Dispose);
|
||||
}
|
||||
private void Dispose()
|
||||
{
|
||||
UnityWorldChunkService.Singleton.Unregister(this);
|
||||
}
|
||||
protected virtual void OnLodChanged(int oldLod, int newLod)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
var bounds = GetBounds();
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawWireCube(bounds.center, bounds.size);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Quadtree;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.OpenWorld
|
||||
{
|
||||
/// <summary>
|
||||
/// 这个应该载入后就销毁,托管给纯class
|
||||
/// </summary>
|
||||
public sealed class ColliderChunkObject : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Collider[] colliders;
|
||||
[SerializeField] private ChunkBehaviour chunkBehaviour;
|
||||
private void Start()
|
||||
{
|
||||
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)
|
||||
{
|
||||
var enabledCollider = arg2 is 0;
|
||||
foreach (var x in colliders)
|
||||
{
|
||||
try
|
||||
{
|
||||
x.enabled = enabledCollider;
|
||||
}
|
||||
catch (UnassignedReferenceException)
|
||||
{
|
||||
GetCollidersInChildren();
|
||||
OnLodChanged(arg1, arg2);
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.Warning<ColliderChunkObject>(gameObject.name);
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
[BIT]
|
||||
private void GetCollidersInChildren()
|
||||
{
|
||||
colliders = GetComponentsInChildren<Collider>();
|
||||
#if UNITY_EDITOR
|
||||
EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
23
Assets/BITKit/Unity/Scripts/WorldChunk/IChunkService.cs
Normal file
23
Assets/BITKit/Unity/Scripts/WorldChunk/IChunkService.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
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
|
||||
{
|
||||
public interface IWorldChunkObject:IItem<IWorldChunkObject,Node<IWorldChunkObject>>
|
||||
{
|
||||
int Id { get; set; }
|
||||
int Lod { get; set; }
|
||||
}
|
||||
public interface IChunkService
|
||||
{
|
||||
void Register(IWorldChunkObject obj);
|
||||
void Unregister(IWorldChunkObject obj);
|
||||
}
|
||||
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace BITKit.WorldChunk
|
||||
{
|
||||
public interface IWorldChunk
|
||||
{
|
||||
Rect GetRect();
|
||||
void SetActive(bool active);
|
||||
}
|
||||
public abstract class WorldChunk : MonoBehaviour, IWorldChunk
|
||||
{
|
||||
public static void Add(IWorldChunk chunk)
|
||||
{
|
||||
chunks.Add(chunk);
|
||||
ChunksArray = chunks.ToArray();
|
||||
}
|
||||
public static void Remove(IWorldChunk chunk)
|
||||
{
|
||||
chunks.Remove(chunk);
|
||||
ChunksArray = chunks.ToArray();
|
||||
}
|
||||
private static readonly List<IWorldChunk> chunks=new();
|
||||
public static IWorldChunk[] ChunksArray { get; private set; }= Array.Empty<IWorldChunk>();
|
||||
public abstract Rect GetRect();
|
||||
public abstract void SetActive(bool active);
|
||||
private void OnEnable()
|
||||
{
|
||||
chunks.Add(this);
|
||||
}
|
||||
private void OnDisable()
|
||||
{
|
||||
chunks.Remove(this);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
namespace BITKit.WorldChunk
|
||||
{
|
||||
public class ObjectChunk : WorldChunk
|
||||
{
|
||||
public Vector2 size;
|
||||
public Renderer[] renderers;
|
||||
Vector2 posCenter
|
||||
{
|
||||
get
|
||||
{
|
||||
var pos = transform.position;
|
||||
return new()
|
||||
{
|
||||
x = pos.x,
|
||||
y = pos.z,
|
||||
};
|
||||
}
|
||||
}
|
||||
public override Rect GetRect()
|
||||
{
|
||||
return new()
|
||||
{
|
||||
position = posCenter,
|
||||
size = size,
|
||||
};
|
||||
}
|
||||
public override void SetActive(bool active)
|
||||
{
|
||||
renderers.ForEach(x =>
|
||||
{
|
||||
x.enabled = active;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
namespace BITKit.WorldChunk
|
||||
{
|
||||
|
||||
public class TerrainChunk : WorldChunk
|
||||
{
|
||||
public Terrain terrain;
|
||||
public override Rect GetRect()
|
||||
{
|
||||
Vector3 size = terrain.terrainData.size;
|
||||
return new(transform.position, size);
|
||||
}
|
||||
public override void SetActive(bool active)
|
||||
{
|
||||
terrain.enabled = active;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
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
|
||||
{
|
||||
|
||||
public class UnityWorldChunkService : WorldChunkService<UnityWorldChunkService>
|
||||
{
|
||||
[Serializable]
|
||||
public struct Unity:IChunkService
|
||||
{
|
||||
public void Register(IWorldChunkObject obj)=>Singleton.Register(obj);
|
||||
|
||||
public void Unregister(IWorldChunkObject obj)=>Singleton.Unregister(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using NativeQuadTree;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace BITKit.WorldChunk
|
||||
{
|
||||
public class WorldChunkManager : MonoBehaviour
|
||||
{
|
||||
public Vector2Int playerSize;
|
||||
private Rect playerRect;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
var quadTree = new NativeQuadTree<int>(new AABB2D(default, new float2(1024,1024)));
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
var cameraPos = Camera.main.transform.position;
|
||||
Vector2 position = new()
|
||||
{
|
||||
x = cameraPos.x - playerSize.x / 2,
|
||||
y = cameraPos.z - playerSize.y / 2,
|
||||
};
|
||||
playerRect = new(position, playerSize);
|
||||
OnUpdate();
|
||||
//ThreadHelper.Add(OnUpdate);
|
||||
}
|
||||
private void OnUpdate()
|
||||
{
|
||||
foreach (var x in WorldChunk.ChunksArray)
|
||||
{
|
||||
var isOverlay = playerRect.Overlaps(x.GetRect());
|
||||
x.SetActive(isOverlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
177
Assets/BITKit/Unity/Scripts/WorldChunk/WorldChunkService.cs
Normal file
177
Assets/BITKit/Unity/Scripts/WorldChunk/WorldChunkService.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
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
|
||||
{
|
||||
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;
|
||||
[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;
|
||||
}
|
||||
|
||||
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 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 async void OnTick(float deltaTime)
|
||||
{
|
||||
if (!enabled) return;
|
||||
if (isBusy) return;
|
||||
|
||||
isBusy = true;
|
||||
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;
|
||||
|
||||
var cycle = 0;
|
||||
|
||||
await UniTask.SwitchToThreadPool();
|
||||
|
||||
foreach (var chunkObject in _quadtree.Find(new Bounds(cameraPosition, Vector3.one * (lodDistances[^1]+lodDistances[0]))))
|
||||
{
|
||||
if (cycle++ > 64)
|
||||
{
|
||||
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()
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Quadtree;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using YooAsset;
|
||||
|
||||
namespace BITKit.OpenWorld
|
||||
{
|
||||
public class WorldTerrainBehaviour : MonoBehaviour,IWorldChunkObject
|
||||
{
|
||||
[SerializeReference, SubclassSelector] private IReference sceneName;
|
||||
[SerializeField] private Vector3 size;
|
||||
[SerializeField] private Vector3 position;
|
||||
[SerializeField, ReadOnly] private int lod = -1;
|
||||
|
||||
private SceneHandle _sceneHandle;
|
||||
|
||||
[BIT]
|
||||
public async void Load()
|
||||
{
|
||||
if (_sceneHandle is not null) return;
|
||||
var stopWatcher = new System.Diagnostics.Stopwatch();
|
||||
stopWatcher.Start();
|
||||
_sceneHandle = YooAssets.LoadSceneAsync(sceneName.Value,LoadSceneMode.Additive,priority:8);
|
||||
await _sceneHandle;
|
||||
stopWatcher.Stop();
|
||||
Debug.Log($"加载场景 {sceneName.Value} 耗时 {stopWatcher.ElapsedMilliseconds}ms");
|
||||
}
|
||||
[BIT]
|
||||
public async void Unload()
|
||||
{
|
||||
if (_sceneHandle is null) return;
|
||||
var stopWatcher = new System.Diagnostics.Stopwatch();
|
||||
stopWatcher.Start();
|
||||
await _sceneHandle.UnloadAsync();
|
||||
_sceneHandle = null;
|
||||
stopWatcher.Stop();
|
||||
Debug.Log($"卸载场景 {sceneName.Value} 耗时 {stopWatcher.ElapsedMilliseconds}ms");
|
||||
}
|
||||
|
||||
public Bounds GetBounds()=>
|
||||
new Bounds(position, size);
|
||||
|
||||
public Node<IWorldChunkObject> ParentNode { get; set; }
|
||||
public void QuadTree_Root_Initialized(IQuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> root)
|
||||
{
|
||||
}
|
||||
public int Id { get; set; }
|
||||
|
||||
public int Lod
|
||||
{
|
||||
get=>lod;
|
||||
set
|
||||
{
|
||||
lod = value;
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
Load();
|
||||
break;
|
||||
default:
|
||||
Unload();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
WorldTerrainService.Singleton.Register(this);
|
||||
destroyCancellationToken.Register(() => WorldTerrainService.Singleton.Unregister(this));
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawWireCube(position, size);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.OpenWorld
|
||||
{
|
||||
public class WorldTerrainService : WorldChunkService<WorldTerrainService>
|
||||
{
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user