整理EntityDatabase代码
This commit is contained in:
1 parent
6c8108e3ea
commit
d9b66edd89
18 files changed
+221
-58
No files matched your search
@@ -1,25 +1,30 @@
|
||||
using System;
|
||||
using Unity.Burst;
|
||||
|
||||
namespace GameCore.TinyECS
|
||||
{
|
||||
public struct ComponentId
|
||||
internal static class ComponentIdHelper
|
||||
{
|
||||
struct Inner<T> where T : unmanaged
|
||||
public static int currentId;
|
||||
}
|
||||
|
||||
public struct ComponentId<T>
|
||||
{
|
||||
public int id;
|
||||
public static readonly SharedStatic<ComponentId<T>> Instance = SharedStatic<ComponentId<T>>.GetOrCreate<ComponentId<T>>();
|
||||
|
||||
[BurstDiscard]
|
||||
static void EnsureInitialized()
|
||||
{
|
||||
public int id;
|
||||
private Inner(int i) => id = i;
|
||||
public static Inner<T> Instance = default;
|
||||
if (Instance.Data.id == 0)
|
||||
{
|
||||
Instance.Data.id = ++ComponentIdHelper.currentId;
|
||||
}
|
||||
}
|
||||
|
||||
static int currentId;
|
||||
|
||||
public static int Get<T>() where T : unmanaged
|
||||
public static int Get()
|
||||
{
|
||||
if (Inner<T>.Instance.id == 0)
|
||||
{
|
||||
Inner<T>.Instance.id = ++currentId;
|
||||
}
|
||||
return Inner<T>.Instance.id;
|
||||
EnsureInitialized();
|
||||
return Instance.Data.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using GameCore.LowLevel;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
|
||||
namespace GameCore.TinyECS
|
||||
{
|
||||
public readonly struct Entity<TEnum> : IEquatable<Entity<TEnum>> where TEnum : unmanaged
|
||||
public readonly struct Entity<TEnum> : IEquatable<Entity<TEnum>> where TEnum : unmanaged, IConvertible
|
||||
{
|
||||
public readonly TEnum type;
|
||||
public readonly int index;
|
||||
@@ -19,7 +20,7 @@ namespace GameCore.TinyECS
|
||||
public override string ToString() => $"Entity<{type}>({index},{generation})";
|
||||
public bool Equals(Entity<TEnum> other) => type.Equals(other.type) && index == other.index && generation == other.generation;
|
||||
public override bool Equals(object obj) => obj is Entity<TEnum> other && Equals(other);
|
||||
public override int GetHashCode() => LowLevelUtility.HashCombine(type.GetHashCode(), index, generation);
|
||||
public override int GetHashCode() => LowLevelUtility.HashCombine(UnsafeUtility.EnumToInt(type), index, generation);
|
||||
public static bool operator ==(Entity<TEnum> lhs, Entity<TEnum> rhs) => lhs.Equals(rhs);
|
||||
public static bool operator !=(Entity<TEnum> lhs, Entity<TEnum> rhs) => !(lhs == rhs);
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using Unity.Collections;
|
||||
using System.Diagnostics;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
|
||||
namespace GameCore.TinyECS
|
||||
{
|
||||
public struct EntityCollection<TEnum> : IDisposable where TEnum : unmanaged
|
||||
public struct EntityCollection<TEnum> : IDisposable
|
||||
where TEnum : unmanaged, IConvertible
|
||||
{
|
||||
private struct Buffer
|
||||
{
|
||||
@@ -60,6 +62,25 @@ namespace GameCore.TinyECS
|
||||
return dataIndex;
|
||||
}
|
||||
|
||||
public int GetIndex(Entity<TEnum> entity)
|
||||
{
|
||||
CheckEntityType(entity);
|
||||
|
||||
if (entity.index >= entityIndexToDataIndex.Length)
|
||||
{
|
||||
throw new Exception($"Invalid entity: {entity}");
|
||||
}
|
||||
|
||||
var index = entityIndexToDataIndex[entity.index];
|
||||
var buf = entityBuffer[index];
|
||||
if (buf.index != entity.index || buf.generation != entity.generation)
|
||||
{
|
||||
throw new Exception($"Invalid entity: {entity}");
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
public bool TryGetIndex(Entity<TEnum> entity, out int index)
|
||||
{
|
||||
CheckEntityType(entity);
|
||||
@@ -115,7 +136,7 @@ namespace GameCore.TinyECS
|
||||
[Conditional("DEBUG")]
|
||||
void CheckEntityType(Entity<TEnum> entity)
|
||||
{
|
||||
if (!entity.type.Equals(entityType))
|
||||
if (!UnsafeUtility.EnumEquals(entityType, entity.type))
|
||||
throw new Exception($"Wrong entity type: {entity.type}");
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace GameCore.TinyECS
|
||||
public bool IsFull => elementCount == MaxElementCount;
|
||||
public bool IsEmpty => elementCount == 0;
|
||||
|
||||
public EntityDataBlockChain(EntityDataBlockMeta blockMeta, int maxElementCountPerBlock)
|
||||
public EntityDataBlockChain(EntityDataBlockMeta blockMeta, int maxElementCountPerBlock = 1024)
|
||||
{
|
||||
this.blockMeta = blockMeta;
|
||||
blockPtrList = default;
|
||||
@@ -72,7 +72,7 @@ namespace GameCore.TinyECS
|
||||
|
||||
void* ComponentPtrAt<T>(int elementIndex) where T : unmanaged
|
||||
{
|
||||
var componentId = ComponentId.Get<T>();
|
||||
var componentId = ComponentId<T>.Get();
|
||||
var componentIndex = blockMeta.componentIdToIndex[componentId];
|
||||
if (componentIndex > 0)
|
||||
{
|
||||
@@ -133,7 +133,16 @@ namespace GameCore.TinyECS
|
||||
elementCount--;
|
||||
}
|
||||
|
||||
public ref T GetData<T>(int index) where T : unmanaged
|
||||
public T GetData<T>(int index) where T : unmanaged
|
||||
{
|
||||
CheckElementIndex(index);
|
||||
var pComponent = ComponentPtrAt<T>(index);
|
||||
if (pComponent == null)
|
||||
throw new Exception($"Invalid component type: {typeof(T)}");
|
||||
return UnsafeUtility.AsRef<T>(pComponent);
|
||||
}
|
||||
|
||||
public ref T GetDataRef<T>(int index) where T : unmanaged
|
||||
{
|
||||
CheckElementIndex(index);
|
||||
var pComponent = ComponentPtrAt<T>(index);
|
||||
@@ -150,7 +159,7 @@ namespace GameCore.TinyECS
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe readonly struct EntityDataBlockView
|
||||
public readonly unsafe struct EntityDataBlockView
|
||||
{
|
||||
private readonly void* ptr;
|
||||
public readonly EntityDataBlockMeta meta;
|
||||
@@ -172,7 +181,7 @@ namespace GameCore.TinyECS
|
||||
|
||||
void* ComponentPtrAt<T>(int elementIndex) where T : unmanaged
|
||||
{
|
||||
var componentId = ComponentId.Get<T>();
|
||||
var componentId = ComponentId<T>.Get();
|
||||
var componentIndex = meta.componentIdToIndex[componentId];
|
||||
if (componentIndex > 0)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace GameCore.TinyECS
|
||||
meta.componentIdToIndex.Length = meta.componentIdToIndex.Capacity;
|
||||
meta.componentIdToOffset.Length = meta.componentIdToOffset.Capacity;
|
||||
|
||||
var id1 = ComponentId.Get<T1>();
|
||||
var id1 = ComponentId<T1>.Get();
|
||||
meta.componentIdToIndex[id1] = 1;
|
||||
meta.componentIdToOffset[id1] = 0;
|
||||
meta.elementSize = UnsafeUtility.SizeOf<T1>();
|
||||
@@ -31,8 +31,8 @@ namespace GameCore.TinyECS
|
||||
meta.componentIdToIndex.Length = meta.componentIdToIndex.Capacity;
|
||||
meta.componentIdToOffset.Length = meta.componentIdToOffset.Capacity;
|
||||
|
||||
var id1 = ComponentId.Get<T1>();
|
||||
var id2 = ComponentId.Get<T2>();
|
||||
var id1 = ComponentId<T1>.Get();
|
||||
var id2 = ComponentId<T2>.Get();
|
||||
meta.componentIdToIndex[id1] = 1;
|
||||
meta.componentIdToIndex[id2] = 2;
|
||||
meta.componentIdToOffset[id1] = (short)LowLevelUtility.OffsetOf<(T1, T2), T1>();
|
||||
|
||||
@@ -6,5 +6,8 @@ namespace GameCore.TinyECS
|
||||
{
|
||||
void Add();
|
||||
void Remove(int index);
|
||||
|
||||
T GetData<T>(int index) where T : unmanaged;
|
||||
ref T GetDataRef<T>(int index) where T : unmanaged;
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,23 @@ using Unity.Mathematics;
|
||||
|
||||
namespace GameCore.TinyECS
|
||||
{
|
||||
public struct EntityDatabase<TEnum, TData> : IDisposable where TEnum : unmanaged where TData : unmanaged, IEntityDataStruct
|
||||
public struct EntityDatabase<TEnum, TData> : IDisposable
|
||||
where TEnum : unmanaged, IConvertible
|
||||
where TData : unmanaged, IEntityDataStruct
|
||||
{
|
||||
public TData dataStruct;
|
||||
public EntityGenerator<TEnum> generator;
|
||||
public EntityCollection<TEnum> collection;
|
||||
|
||||
public int Count => collection.Count;
|
||||
|
||||
public EntityDatabase(TEnum type, TData dataStruct, int capacity = 16)
|
||||
{
|
||||
generator = new (type, capacity, Allocator.Persistent);
|
||||
collection = new (type, capacity, Allocator.Persistent);
|
||||
this.dataStruct = dataStruct;
|
||||
}
|
||||
|
||||
public Entity<TEnum> AddEntity()
|
||||
{
|
||||
var entity = generator.Create();
|
||||
@@ -25,6 +36,18 @@ namespace GameCore.TinyECS
|
||||
dataStruct.Remove(index);
|
||||
}
|
||||
|
||||
public T GetData<T>(Entity<TEnum> entity) where T : unmanaged
|
||||
{
|
||||
var index = collection.GetIndex(entity);
|
||||
return dataStruct.GetData<T>(index);
|
||||
}
|
||||
|
||||
public ref T GetDataRef<T>(Entity<TEnum> entity) where T : unmanaged
|
||||
{
|
||||
var index = collection.GetIndex(entity);
|
||||
return ref dataStruct.GetDataRef<T>(index);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
generator.Dispose();
|
||||
|
||||
@@ -4,7 +4,8 @@ using Unity.Mathematics;
|
||||
|
||||
namespace GameCore.TinyECS
|
||||
{
|
||||
public struct EntityGenerator<TEnum> : IDisposable where TEnum : unmanaged
|
||||
public struct EntityGenerator<TEnum> : IDisposable
|
||||
where TEnum : unmanaged, IConvertible
|
||||
{
|
||||
private NativeList<int> indexToGeneration;
|
||||
private int beginSearchIndex;
|
||||
|
||||
@@ -4,25 +4,10 @@
|
||||
"references": [
|
||||
"Unity.Collections",
|
||||
"Unity.Mathematics",
|
||||
"nimin.lowlevel"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Android",
|
||||
"Editor",
|
||||
"iOS",
|
||||
"LinuxStandalone64",
|
||||
"Lumin",
|
||||
"macOSStandalone",
|
||||
"PS4",
|
||||
"Stadia",
|
||||
"Switch",
|
||||
"tvOS",
|
||||
"WSA",
|
||||
"WebGL",
|
||||
"WindowsStandalone32",
|
||||
"WindowsStandalone64",
|
||||
"XboxOne"
|
||||
"nimin.lowlevel",
|
||||
"Unity.Burst"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
|
||||
Reference in new issue
Block a user