diff --git a/src/Builtin/Subjects.cs b/src/Builtin/Subjects.cs index fbf8462..03b6d25 100644 --- a/src/Builtin/Subjects.cs +++ b/src/Builtin/Subjects.cs @@ -1,11 +1,11 @@ namespace DCFApixels.DragonECS { - public class SingleSubject : EcsSubject where TPool : IEcsPoolImplementation, new() + public class SingleSubject : EcsSubject where TPool : IEcsPoolImplementation, new() { public readonly TPool pool; public SingleSubject(Builder b) { - pool = b.Include(); + pool = b.Include(); } } public class CombinedSubject : EcsSubject diff --git a/src/EcsSubject.cs b/src/EcsSubject.cs index 9fbfbf0..57829d1 100644 --- a/src/EcsSubject.cs +++ b/src/EcsSubject.cs @@ -68,35 +68,35 @@ namespace DCFApixels.DragonECS } #region Include/Exclude/Optional - public sealed override TPool Include() + public sealed override TPool Include() { - IncludeImplicit(); - return _world.GetPool(); + IncludeImplicit(typeof(TPool).GetGenericArguments()[0]); + return _world.GetPool(); } - public sealed override TPool Exclude() + public sealed override TPool Exclude() { - ExcludeImplicit(); - return _world.GetPool(); + ExcludeImplicit(typeof(TPool).GetGenericArguments()[0]); + return _world.GetPool(); } - public sealed override TPool Optional() + public sealed override TPool Optional() { - return _world.GetPool(); + return _world.GetPool(); } - private void IncludeImplicit() + private void IncludeImplicit(Type type) { - int id = _world.GetComponentID(); + int id = _world.GetComponentID(type); #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (_inc.Contains(id) || _exc.Contains(id)) throw new EcsFrameworkException($"{typeof(TComponent).Name} already in constraints list."); + if (_inc.Contains(id) || _exc.Contains(id)) throw new EcsFrameworkException($"{type.Name} already in constraints list."); #endif - _inc.Add(_world.GetComponentID()); + _inc.Add(id); } - private void ExcludeImplicit() + private void ExcludeImplicit(Type type) { - int id = _world.GetComponentID(); + int id = _world.GetComponentID(type); #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (_inc.Contains(id) || _exc.Contains(id)) throw new EcsFrameworkException($"{typeof(TComponent).Name} already in constraints list."); + if (_inc.Contains(id) || _exc.Contains(id)) throw new EcsFrameworkException($"{type.Name} already in constraints list."); #endif - _exc.Add(_world.GetComponentID()); + _exc.Add(id); } #endregion @@ -127,13 +127,13 @@ namespace DCFApixels.DragonECS #if UNITY_2020_3_OR_NEWER [UnityEngine.Scripting.Preserve] #endif - private void SupportReflectionHack() where TPool : IEcsPoolImplementation, new() + private void SupportReflectionHack() where TPool : IEcsPoolImplementation, new() { - Include(); - Exclude(); - Optional(); - IncludeImplicit(); - ExcludeImplicit(); + Include(); + Exclude(); + Optional(); + IncludeImplicit(null); + ExcludeImplicit(null); } #endregion } @@ -154,9 +154,9 @@ namespace DCFApixels.DragonECS #region BuilderBase public abstract class EcsSubjectBuilderBase { - public abstract TPool Include() where TPool : IEcsPoolImplementation, new(); - public abstract TPool Exclude() where TPool : IEcsPoolImplementation, new(); - public abstract TPool Optional() where TPool : IEcsPoolImplementation, new(); + public abstract TPool Include() where TPool : IEcsPoolImplementation, new(); + public abstract TPool Exclude() where TPool : IEcsPoolImplementation, new(); + public abstract TPool Optional() where TPool : IEcsPoolImplementation, new(); } #endregion diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 5fba16a..c01d4cd 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -104,7 +104,8 @@ namespace DCFApixels.DragonECS #endregion #region ComponentInfo - public int GetComponentID() => WorldMetaStorage.GetComponentId(_worldTypeID); + public int GetComponentID() => WorldMetaStorage.GetComponentID(_worldTypeID); + public int GetComponentID(Type type) => WorldMetaStorage.GetComponentID(type, _worldTypeID); public Type GetComponentType(int componentID) => WorldMetaStorage.GetComponentType(_worldTypeID, componentID); public bool IsComponentTypeDeclared() => IsComponentTypeDeclared(typeof(T)); public bool IsComponentTypeDeclared(Type type) => WorldMetaStorage.IsComponentTypeDeclared(_worldTypeID, type); @@ -114,9 +115,9 @@ namespace DCFApixels.DragonECS #if UNITY_2020_3_OR_NEWER [UnityEngine.Scripting.Preserve] #endif - public TPool GetPool() where TPool : IEcsPoolImplementation, new() + public TPool GetPool() where TPool : IEcsPoolImplementation, new() { - int uniqueID = WorldMetaStorage.GetComponentId(_worldTypeID); + int uniqueID = WorldMetaStorage.GetPoolID(_worldTypeID); if (uniqueID >= _pools.Length) { int oldCapacity = _pools.Length; @@ -133,7 +134,7 @@ namespace DCFApixels.DragonECS } public TSubject GetSubject() where TSubject : EcsSubject { - int uniqueID = WorldMetaStorage.GetSubjectId(_worldTypeID); + int uniqueID = WorldMetaStorage.GetSubjectID(_worldTypeID); if (uniqueID >= _subjects.Length) Array.Resize(ref _subjects, _subjects.Length << 1); if (_subjects[uniqueID] == null) @@ -142,7 +143,7 @@ namespace DCFApixels.DragonECS } public TExecutor GetExecutor() where TExecutor : EcsQueryExecutor, new() { - int index = WorldMetaStorage.GetExecutorId(_worldTypeID); + int index = WorldMetaStorage.GetExecutorID(_worldTypeID); if (index >= _executors.Length) Array.Resize(ref _executors, _executors.Length << 1); if (_executors[index] == null) @@ -155,7 +156,7 @@ namespace DCFApixels.DragonECS } public T Get() where T : class, new() { - int index = WorldMetaStorage.GetWorldComponentId(_worldTypeID); + int index = WorldMetaStorage.GetWorldComponentID(_worldTypeID); if (index >= _components.Length) Array.Resize(ref _executors, _executors.Length << 1); diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index aead37f..81724d7 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -199,20 +199,20 @@ namespace DCFApixels.DragonECS { public static EcsPool GetPool(this EcsWorld self) where TComponent : struct, IEcsComponent { - return self.GetPool>(); + return self.GetPool>(); } public static EcsPool Include(this EcsSubjectBuilderBase self) where TComponent : struct, IEcsComponent { - return self.Include>(); + return self.Include>(); } public static EcsPool Exclude(this EcsSubjectBuilderBase self) where TComponent : struct, IEcsComponent { - return self.Exclude>(); + return self.Exclude>(); } public static EcsPool Optional(this EcsSubjectBuilderBase self) where TComponent : struct, IEcsComponent { - return self.Optional>(); + return self.Optional>(); } } } diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index 1b83619..342de05 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -191,20 +191,20 @@ namespace DCFApixels.DragonECS { public static EcsTagPool GetPool(this EcsWorld self) where TTagComponent : struct, IEcsTagComponent { - return self.GetPool>(); + return self.GetPool>(); } public static EcsTagPool Include(this EcsSubjectBuilderBase self) where TTagComponent : struct, IEcsTagComponent { - return self.Include>(); + return self.Include>(); } public static EcsTagPool Exclude(this EcsSubjectBuilderBase self) where TTagComponent : struct, IEcsTagComponent { - return self.Exclude>(); + return self.Exclude>(); } public static EcsTagPool Optional(this EcsSubjectBuilderBase self) where TTagComponent : struct, IEcsTagComponent { - return self.Optional>(); + return self.Optional>(); } } } diff --git a/src/Utils/WorldMetaStorage.cs b/src/Utils/WorldMetaStorage.cs index 5c44d76..5b36a5b 100644 --- a/src/Utils/WorldMetaStorage.cs +++ b/src/Utils/WorldMetaStorage.cs @@ -5,7 +5,8 @@ using System.Runtime.CompilerServices; namespace DCFApixels.DragonECS { - internal static class WorldMetaStorage + //TODO этот класс требует переработки, изначально такая конструкция имела хорошую производительность, но сейчас он слишком раздулся + internal static class WorldMetaStorage { private static int _tokenCount = 0; private static List _resizers = new List(); @@ -37,15 +38,18 @@ namespace DCFApixels.DragonECS return id; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetWorldId() => WorldIndex.id; + public static int GetWorldID() => WorldIndex.id; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetComponentId(int worldID) => Component.Get(worldID); + public static int GetComponentID(int worldID) => Component.Get(worldID); + public static int GetComponentID(Type type, int worldID) => _metas[worldID].GetComponentID(type); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetSubjectId(int worldID) => Subject.Get(worldID); + public static int GetPoolID(int worldID) => Pool.Get(worldID); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetExecutorId(int worldID) => Executor.Get(worldID); + public static int GetSubjectID(int worldID) => Subject.Get(worldID); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetWorldComponentId(int worldID) => WorldComponent.Get(worldID); + public static int GetExecutorID(int worldID) => Executor.Get(worldID); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetWorldComponentID(int worldID) => WorldComponent.Get(worldID); public static bool IsComponentTypeDeclared(int worldID, Type type) => _metas[worldID].IsDeclaredType(type); public static Type GetComponentType(int worldID, int componentID) => _metas[worldID].GetComponentType(componentID); @@ -58,14 +62,54 @@ namespace DCFApixels.DragonECS } #region Containers + public static class PoolComponentIdArrays + { + private static Dictionary _componentTypeArrayPairs = new Dictionary(); + + public static int[] GetIdsArray(Type type) + { + int targetSize = _tokenCount; + if (!_componentTypeArrayPairs.TryGetValue(type, out int[] result)) + { + result = new int[targetSize]; + for (int i = 0; i < result.Length; i++) + result[i] = -1; + _componentTypeArrayPairs.Add(type, result); + } + else + { + if(result.Length < targetSize) + { + int oldSize = result.Length; + Array.Resize(ref result, targetSize); + ArrayUtility.Fill(result, -1, oldSize, targetSize); + _componentTypeArrayPairs[type] = result; + } + } + + return result; + } + + public static int GetComponentID(Type type, int token) + { + GetIdsArray(type); + ref int id = ref _componentTypeArrayPairs[type][token]; + if (id < 0) + { + var meta = _metas[token]; + id = meta.componentCount++; + meta.AddType(id, type); + } + return id; + } + } private static class Pool { public static int[] ids; + private static Type componentType = typeof(T).GetGenericArguments()[0]; static Pool() { - ids = new int[_tokenCount]; - for (int i = 0; i < ids.Length; i++) - ids[i] = -1; + ids = PoolComponentIdArrays.GetIdsArray(componentType); _resizers.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -74,9 +118,7 @@ namespace DCFApixels.DragonECS ref int id = ref ids[token]; if (id < 0) { - var meta = _metas[token]; - id = meta.GetComponentID(typeof(T).GetGenericArguments()[0]); - meta.AddType(id, typeof(T)); + id = PoolComponentIdArrays.GetComponentID(componentType, token); } return id; } @@ -86,9 +128,7 @@ namespace DCFApixels.DragonECS public override int[] IDS => ids; public override void Resize(int size) { - int oldSize = ids.Length; - Array.Resize(ref ids, size); - ArrayUtility.Fill(ids, -1, oldSize, size); + ids = PoolComponentIdArrays.GetIdsArray(componentType); } } } @@ -97,9 +137,7 @@ namespace DCFApixels.DragonECS public static int[] ids; static Component() { - ids = new int[_tokenCount]; - for (int i = 0; i < ids.Length; i++) - ids[i] = -1; + ids = PoolComponentIdArrays.GetIdsArray(typeof(T)); _resizers.Add(new Resizer()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -108,9 +146,7 @@ namespace DCFApixels.DragonECS ref int id = ref ids[token]; if (id < 0) { - var meta = _metas[token]; - id = meta.componentCount++; - meta.AddType(id, typeof(T)); + id = PoolComponentIdArrays.GetComponentID(typeof(T), token); } return id; } @@ -120,9 +156,7 @@ namespace DCFApixels.DragonECS public override int[] IDS => ids; public override void Resize(int size) { - int oldSize = ids.Length; - Array.Resize(ref ids, size); - ArrayUtility.Fill(ids, -1, oldSize, size); + ids = PoolComponentIdArrays.GetIdsArray(typeof(T)); } } } @@ -218,6 +252,7 @@ namespace DCFApixels.DragonECS } #endregion + public struct XXX : IEcsComponent { } private class WorldTypeMeta { public int id; @@ -239,12 +274,7 @@ namespace DCFApixels.DragonECS public bool IsDeclaredType(Type type) => _declaredComponentTypes.ContainsKey(type); public int GetComponentID(Type type) { - if (!IsDeclaredType(type)) - { - RuntimeHelpers.RunClassConstructor(type.TypeHandle); - typeof(Component<>).MakeGenericType(type); - } - return _declaredComponentTypes[type]; + return PoolComponentIdArrays.GetComponentID(type, id); } public WorldTypeMeta() {