Skip to content

Commit

Permalink
ECS - add bool property EntityStore.RecycleIds
Browse files Browse the repository at this point in the history
  • Loading branch information
friflo committed Jul 31, 2024
1 parent 769f77d commit 55ff515
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 12 deletions.
10 changes: 10 additions & 0 deletions src/ECS/Entity/Store/Entities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,16 @@ internal void CreateEntityNodes(Archetype archetype, int count)
archetype.entityCount += count;
}

private void SetRecycleIds (bool enable) {
if (enable == recycleIds) {
return;
}
recycleIds = enable;
if (!enable) {
intern.recycleIds.Clear();
}
}

/// <summary>
/// Set the passed <paramref name="entity"/> as the <see cref="StoreRoot"/> entity.
/// </summary>
Expand Down
30 changes: 18 additions & 12 deletions src/ECS/Entity/Store/NodeTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -455,13 +455,15 @@ private void NewIds(int[] ids, int start, int count, Archetype archetype)
{
var localNodes = nodes;
int n = 0;
for (; n < count; n++)
{
if (!intern.recycleIds.TryPop(out int id)) {
break;
if (recycleIds) {
for (; n < count; n++)
{
if (!intern.recycleIds.TryPop(out int id)) {
break;
}
localNodes[id].archetype = archetype; // mark created. So id is not used twice by loop below
ids[n + start] = id;
}
localNodes[id].archetype = archetype; // mark created. So id is not used twice by loop below
ids[n + start] = id;
}
int max = localNodes.Length;
int sequenceId = intern.sequenceId;
Expand All @@ -484,12 +486,14 @@ internal int NewId()
{
var localNodes = nodes;
int id;
while (intern.recycleIds.TryPop(out id))
{
if (localNodes[id].archetype != null) {
continue;
if (recycleIds) {
while (intern.recycleIds.TryPop(out id))
{
if (localNodes[id].archetype != null) {
continue;
}
return id;
}
return id;
}
int max = localNodes.Length;
id = ++intern.sequenceId;
Expand All @@ -508,7 +512,9 @@ internal int NewId()
internal void DeleteNode(Entity entity)
{
int id = entity.Id;
intern.recycleIds.Push(id);
if (recycleIds) {
intern.recycleIds.Push(id);
}
entityCount--;
ref var node = ref nodes[id];
if (node.isOwner != 0) {
Expand Down
4 changes: 4 additions & 0 deletions src/ECS/EntityStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public sealed partial class EntityStore : EntityStoreBase
/// <summary> Get the number of internally reserved entities. </summary>
[Browse(Never)] public int Capacity => nodes.Length;

[Browse(Never)] public bool RecycleIds { get => recycleIds; set => SetRecycleIds(value); }

/// <summary> Return store information used for debugging and optimization. </summary>
// ReSharper disable once InconsistentNaming
[Browse(Never)] public readonly EntityStoreInfo Info;
Expand Down Expand Up @@ -104,6 +106,7 @@ public sealed partial class EntityStore : EntityStoreBase
// --- Note: all fields must stay private to limit the scope of mutations
[Browse(Never)] internal EntityNode[] nodes; // 8 - acts also id2pid
[Browse(Never)] private Entity storeRoot; // 16 - origin of the tree graph. null if no origin assigned
[Browse(Never)] private bool recycleIds; // 1

// --- buffers
[Browse(Never)] private int[] idBuffer; // 8
Expand Down Expand Up @@ -156,6 +159,7 @@ public EntityStore(PidType pidType)
EnsureNodesLength(2);
idBuffer = new int[1];
idBufferSet = new HashSet<int>();
recycleIds = true;
dataBuffer = new DataEntity();
Info = new EntityStoreInfo(this);
}
Expand Down
28 changes: 28 additions & 0 deletions src/Tests/ECS/Entity/Test_StructHeap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,34 @@ public static void Test_StructHeap_CreateEntities_with_pids()
Assert.AreEqual(count, type.Count);
}

[Test]
public static void Test_StructHeap_RecycleIds_Disabled()
{
var store = new EntityStore { RecycleIds = false };
store.RecycleIds = false;
var entity1 = store.CreateEntity();
var entity2 = store.CreateEntity();
entity1.DeleteEntity();
entity2.DeleteEntity();

var entity3 = store.CreateEntity();
var entity4 = store.CreateEntity();
Assert.AreEqual(3, entity3.Id);
Assert.AreEqual(4, entity4.Id);

// --- can change RecycleIds state on store
store.RecycleIds = true;
entity4.DeleteEntity();
entity3.DeleteEntity();

var entity3b = store.CreateEntity();
Assert.AreEqual(3, entity3b.Id);

store.RecycleIds = false;
var entity5 = store.CreateEntity();
Assert.AreEqual(5, entity5.Id);
}

[Test]
public static void Test_StructHeap_CreateEntity_RecycleIds()
{
Expand Down

0 comments on commit 55ff515

Please sign in to comment.