diff --git a/Ghost.Entities.Test/EntityTest.cs b/Ghost.Entities.Test/EntityTest.cs index 6804904..885b9cd 100644 --- a/Ghost.Entities.Test/EntityTest.cs +++ b/Ghost.Entities.Test/EntityTest.cs @@ -14,7 +14,7 @@ internal struct TestChunkQueryJob : IJobChunk var transforms = view.GetComponentDataRW(); for (var i = 0; i < view.Count; i++) { - transforms[i].position += random.NextFloat3(-1f, 1f); + transforms[i].position += random.NextFloat3(); } } } diff --git a/Ghost.Entities/Archetype.cs b/Ghost.Entities/Archetype.cs index 455ce20..1c83975 100644 --- a/Ghost.Entities/Archetype.cs +++ b/Ghost.Entities/Archetype.cs @@ -23,93 +23,81 @@ internal unsafe sealed class ChunkDebugView } } - public byte* pData; - public int count; - public int capacity; - public int worldID; - public int archetypeID; + private Chunk _chunk; public ChunkDebugView(Chunk chunk) { - pData = chunk.GetUnsafePtr(); - count = chunk._count; - capacity = chunk._capacity; -#if DEBUG || GHOST_EDITOR - worldID = chunk._worldID; - archetypeID = chunk._archetypeID; -#else - worldID = -1; - archetypeID = -1; -#endif + _chunk = chunk; } [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - public object[] Items - { - get - { -#if !(DEBUG || GHOST_EDITOR) -#else - if (count == 0) -#endif - { - return []; - } + public object[] Items => GetItems(in _chunk); - var views = new List(); - var r = World.GetWorld(worldID); - if (!r) - { - return []; - } - - ref var archetype = ref r.Value.GetArchetypeReference(archetypeID); - var it = archetype._signature.GetIterator(); - while (it.Next(out var index)) - { - var type = Type.GetTypeFromHandle(RuntimeTypeHandle.FromIntPtr(ComponentRegister.s_runtimeIDToTypeHandle[index])); - if (type == null) - { - continue; - } - - var layout = archetype.GetLayout(index).Value; - var readMethod = typeof(ChunkDebugView) - .GetMethod(nameof(ReadComponentArray), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)! - .MakeGenericMethod(type); - - // 3. Invoke it to get a Position[] or Velocity[] - var array = readMethod.Invoke(this, [layout.offset]); - if (array == null) - { - continue; - } - - // 4. Wrap it in a nice label so the debugger shows "Position[]" - views.Add(new ComponentArrayView(type.Name, array)); - } - - return [.. views]; - } - } - - private T[] ReadComponentArray(int offsetInChunk) + private static T[] ReadComponentArray(long pData, int offsetInChunk, int count) where T : unmanaged { var result = new T[count]; unsafe { - var basePtr = pData + offsetInChunk; - - var sizeOfT = sizeof(T); - for (int i = 0; i < count; i++) - { - // Read directly from raw memory - result[i] = Unsafe.Read(basePtr + (i * sizeOfT)); - } + var basePtr = (byte*)pData + offsetInChunk; + var span = new Span(basePtr, count); + span.CopyTo(result); } + return result; } + + private static object[] GetItems(ref readonly Chunk chunk) + { +#if !(DEBUG || GHOST_EDITOR) + return []; +#else + var pData = chunk.GetUnsafePtr(); + var count = chunk._count; + var capacity = chunk._capacity; + var worldID = chunk._worldID; + var archetypeID = chunk._archetypeID; + + if (count == 0) + { + return []; + } + + var views = new List(); + var r = World.GetWorld(worldID); + if (!r) + { + return []; + } + + ref var archetype = ref r.Value.GetArchetypeReference(archetypeID); + var it = archetype._signature.GetIterator(); + while (it.Next(out var index)) + { + var type = ComponentRegister.s_runtimeIDToType[index]; + if (type == null) + { + continue; + } + var layout = archetype.GetLayout(index).Value; + var readMethod = typeof(ChunkDebugView) + .GetMethod(nameof(ReadComponentArray), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)! + .MakeGenericMethod(type); + + // 3. Invoke it to get a Position[] or Velocity[] + var array = readMethod.Invoke(null, [(long)pData, layout.offset, count]); + if (array == null) + { + continue; + } + + // 4. Wrap it in a nice label so the debugger shows "Position[]" + views.Add(new ComponentArrayView(type.Name, array)); + } + + return [.. views]; +#endif + } } [DebuggerTypeProxy(typeof(ChunkDebugView))] @@ -509,7 +497,7 @@ internal unsafe struct Archetype : IIdentifierType, IDisposable // Only operate the swap back after the update is succeed. MemoryUtility.MemCpy(pRowEntity, pLastEntity, (nuint)sizeof(Entity)); - for (var i = 0; i <= _layouts.Count; i++) + for (var i = 0; i < _layouts.Count; i++) { var layout = _layouts[i]; diff --git a/Ghost.Entities/Component.cs b/Ghost.Entities/Component.cs index babe253..f73e0b0 100644 --- a/Ghost.Entities/Component.cs +++ b/Ghost.Entities/Component.cs @@ -37,7 +37,7 @@ internal static class ComponentRegister private static readonly Dictionary s_typeHandleToID = new(); private static readonly Dictionary s_nameToRuntimeID = new(); #if DEBUG || GHOST_EDITOR - internal static readonly Dictionary s_runtimeIDToTypeHandle = new(); + internal static readonly Dictionary s_runtimeIDToType = new(); #endif public static unsafe Identifier GetOrRegisterComponent() @@ -72,7 +72,7 @@ internal static class ComponentRegister s_typeHandleToID[typeHandle] = newID; s_nameToRuntimeID[stableName] = newID; #if DEBUG || GHOST_EDITOR - s_runtimeIDToTypeHandle[newID.value] = typeHandle; + s_runtimeIDToType[newID.value] = typeof(T); #endif return newID;