diff --git a/src/Arch/Core/Query.cs b/src/Arch/Core/Query.cs index feed4a1e..6b8359b5 100644 --- a/src/Arch/Core/Query.cs +++ b/src/Arch/Core/Query.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.Contracts; using Arch.Core.Extensions; using Arch.Core.Extensions.Internal; using Arch.Core.Utils; @@ -571,6 +572,22 @@ internal Query(Archetypes allArchetypes, QueryDescription description) _queryDescription = description; } + /// + /// Counts all s that match this query. + /// + [Pure] + public int CountEntities() + { + var counter = 0; + foreach (var archetype in GetArchetypeIterator()) + { + var entities = archetype.EntityCount; + counter += entities; + } + + return counter; + } + /// /// Checks whether the specified matches. /// diff --git a/src/Arch/Core/World.cs b/src/Arch/Core/World.cs index 82c6a5ab..38c5b062 100644 --- a/src/Arch/Core/World.cs +++ b/src/Arch/Core/World.cs @@ -410,17 +410,30 @@ public void Destroy(Entity entity) [Pure] public Query Query(in QueryDescription queryDescription) { - // Looping over all archetypes, their chunks and their entities. - var queryCache = QueryCache; // Storing locally to only access the QueryCache once + var queryCache = QueryCache; // Store locally to only access the field once + + #if NET6_0_OR_GREATER + ref var queryRef = ref CollectionsMarshal.GetValueRefOrAddDefault(queryCache, queryDescription, out bool exists); + if (exists) + { + return queryRef!; + } + else + { + var newQuery = new Query(Archetypes, queryDescription); + queryRef = newQuery; + return newQuery; + } + #else if (queryCache.TryGetValue(queryDescription, out var query)) { return query; } query = new Query(Archetypes, queryDescription); - queryCache[queryDescription] = query; - + queryCache.Add(queryDescription, query); return query; + #endif } ///