Per-component versioning and change tracking for ECS

Introduce per-component versioning in chunks and world for efficient change detection.
- Add version arrays to chunks and global version to world.
- Update queries and ForEach to mark written components as changed.
- Extend QueryBuilder with WithAllRW/WithPresentRW for write access.
- Expose change tracking API in ChunkView.
- Improve thread safety and debug code.
- Update tests and examples to demonstrate new features.
This commit is contained in:
2025-12-10 19:01:25 +09:00
parent 21e85e0c02
commit 856fa4f07d
11 changed files with 968 additions and 93 deletions

View File

@@ -1,6 +1,7 @@
using Ghost.Core;
using Misaki.HighPerformance.LowLevel.Collections;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Runtime.CompilerServices;
namespace Ghost.Entities;
@@ -18,6 +19,7 @@ public struct ComponentInfo
public Identifier<IComponent> id;
public int size;
public int alignment;
public int lastWriteVersion;
public bool isEnableable;
}
@@ -77,6 +79,7 @@ internal static class ComponentRegister
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Identifier<IComponent> GetComponentID(Type type)
{
var typeHandle = type.TypeHandle.Value;
@@ -91,9 +94,24 @@ internal static class ComponentRegister
throw new KeyNotFoundException($"Component type {type} is not registered.");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ComponentInfo GetComponentInfo(Identifier<IComponent> typeId)
{
return s_registeredComponents[typeId];
lock (s_registeredComponents)
{
return s_registeredComponents[typeId];
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetComponentLastWrite(Identifier<IComponent> typeId, int version)
{
lock (s_registeredComponents)
{
var info = s_registeredComponents[typeId];
info.lastWriteVersion = version;
s_registeredComponents[typeId] = info;
}
}
public static int GetHashCode(params ReadOnlySpan<Identifier<IComponent>> componentTypeIDs)