This commit is contained in:
CortexCore
2024-03-31 23:31:00 +08:00
parent e179d2eb53
commit b7b89ee71a
641 changed files with 31286 additions and 22134 deletions

View File

@@ -0,0 +1,12 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit.OpenWorld
{
public class AIChunkService : WorldChunkService<AIChunkService>
{
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 1ab742126d040ee4ab352aaf114e2d1c
guid: a003b9287ee730a4e92137b6a84c0104
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,10 +1,14 @@
{
"name": "BITKit.WorkdChunk",
"name": "BITKit.WorldChunk",
"rootNamespace": "",
"references": [
"GUID:a209c53514018594f9f482516f2a6781",
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
"GUID:9400d40641bab5b4a9702f65bf5c6eb5"
"GUID:1193c2664d97cc049a6e4c486c6bce71",
"GUID:d8b63aba1907145bea998dd612889d6b",
"GUID:d525ad6bd40672747bde77962f1c401e",
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:f51ebe6a0ceec4240a699833d6309b23"
],
"includePlatforms": [],
"excludePlatforms": [],

View File

@@ -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;
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 7dce32649c9e8f14dab8ae0b8e81af52
guid: 32a552c73063aba4fa13802e02b22df9
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,41 @@
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);
}
size = bounds.size;
offset = bounds.center - transform.position;
EditorUtility.SetDirty(this);
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: bb0548fad33ba7f4db78c44ce4f8e12a
guid: 5141b62a57a90f14bb91d60a776b7d30
MonoImporter:
externalObjects: {}
serializedVersion: 2

View 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);
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: cd08b934457f16d45935461c91d661aa
guid: 83a934099fe5d8643bbaab86ed3f866b
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -0,0 +1,53 @@
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()=>new Bounds(transform.position+transform.rotation * offset,transform.rotation * size);
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()
{
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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e23549f6ffcd5244cbd08e3dae427005
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
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()
{
chunkBehaviour.OnLodChangedEvent += OnLodChanged;
if(colliders is {Length:0})colliders = GetComponentsInChildren<Collider>();
}
private void OnLodChanged(int arg1, int arg2)
{
var enabledCollider = arg2 is 0;
foreach (var x in colliders)
{
x.enabled = enabledCollider;
}
}
#if UNITY_EDITOR
[BIT]
private void GetCollidersInChildren()
{
colliders = GetComponentsInChildren<Collider>();
EditorUtility.SetDirty(this);
}
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 607dd8bacfc005c4482206db1b79203f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View 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);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a03edf3b55b16f540ae9e0838ce9d962
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -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;
});
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aee50108772796b46b557b1b11cb9d56
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,32 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
namespace BITKit.WorldChunk
{
public class WorldChunkManager : MonoBehaviour
{
public Vector2Int playerSize;
private Rect playerRect;
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);
}
}
}
}

View 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);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d369ea595d83d94387c6f975790067d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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,suspendLoad:true,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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 036c09833b5af014a96acf475ad913ec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BITKit.OpenWorld
{
public class WorldTerrainService : WorldChunkService<WorldTerrainService>
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 621bedf5aebf7d445896c3309de4ff70
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: