From 37718d354a173cc82aa1ba428d1c36506b0dffec Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:52:19 +0800 Subject: [PATCH] fixes/optimization --- src/Collections/EcsSpan.cs | 3 +- src/Internal/SortHalper.cs | 424 ++++++++++++++++++++++++++++++------- src/Pools/EcsPool.cs | 20 +- src/Pools/EcsPoolBase.cs | 97 +++------ src/Pools/EcsTagPool.cs | 12 +- 5 files changed, 390 insertions(+), 166 deletions(-) diff --git a/src/Collections/EcsSpan.cs b/src/Collections/EcsSpan.cs index d31c25b..02a9351 100644 --- a/src/Collections/EcsSpan.cs +++ b/src/Collections/EcsSpan.cs @@ -322,7 +322,7 @@ namespace DCFApixels.DragonECS } namespace DCFApixels.DragonECS.Core -{ +{ #if ENABLE_IL2CPP using Unity.IL2CPP.CompilerServices; [Il2CppSetOption(Option.NullChecks, false)] @@ -385,6 +385,7 @@ namespace DCFApixels.DragonECS.Core #endregion #region Constructors + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal EcsUnsafeSpan(short worldID, int* array, int length) { _worldID = worldID; diff --git a/src/Internal/SortHalper.cs b/src/Internal/SortHalper.cs index 0b9a619..31e4c49 100644 --- a/src/Internal/SortHalper.cs +++ b/src/Internal/SortHalper.cs @@ -17,51 +17,53 @@ namespace DCFApixels.DragonECS.Core.Internal #endif internal static unsafe class SortHalper { - internal static StructComparison ToStruct(this Comparison self) - { - return new StructComparison(self); - } - internal static StructComparer ToStruct(this Comparer self) - { - return new StructComparer(self); - } + #region Span + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sort(Span span) { - var c = Comparer.Default.ToStruct(); - SortHalper>.Sort(span, ref c); + var c = new ComparerWrapper(Comparer.Default); + SortHalper>.Sort(span, ref c); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Sort(Span span, bool _ = false) + where T : IComparable + { + var c = new ComparableWrapper(); + SortHalper>.Sort(span, ref c); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sort(Span span, Comparer comparer) { - var c = comparer.ToStruct(); - SortHalper>.Sort(span, ref c); + var c = new ComparerWrapper(comparer); + SortHalper>.Sort(span, ref c); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sort(Span span, Comparison comparison) { - var c = comparison.ToStruct(); - SortHalper>.Sort(span, ref c); + var c = new ComparisonWrapper(comparison); + SortHalper>.Sort(span, ref c); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sort(Span span, ref TComparer comparer) where TComparer : struct, IComparer { SortHalper.Sort(span, ref comparer); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sort(Span span, TComparer comparer) where TComparer : struct, IComparer { SortHalper.Sort(span, ref comparer); } + #endregion - + #region Utils // Таблица для De Bruijn-умножения (позиция старшего бита для чисел 0..31) private const int Log2DeBruijn32_Length = 32; private static readonly uint* Log2DeBruijn32 = MemoryAllocator.From(new uint[Log2DeBruijn32_Length] { - 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, - 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, - 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, - 4, 31 - //0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, - //8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }).Ptr; /// 32-битный логарифм по основанию 2 (округление вниз). Для value = 0 возвращает 0. @@ -98,34 +100,7 @@ namespace DCFApixels.DragonECS.Core.Internal return 32 + Log2(high); } } - } -#if ENABLE_IL2CPP - [Il2CppSetOption(Option.NullChecks, false)] - [Il2CppSetOption(Option.ArrayBoundsChecks, false)] -#endif - internal readonly struct StructComparison : IComparer - { - public readonly Comparison Comparison; - public StructComparison(Comparison comparison) - { - Comparison = comparison; - } - public int Compare(T x, T y) - { - return Comparison(x, y); - } - } - internal readonly struct StructComparer : IComparer - { - public readonly Comparer Comparer; - public StructComparer(Comparer comparer) - { - Comparer = comparer; - } - public int Compare(T x, T y) - { - return Comparer.Compare(x, y); - } + #endregion } // a > b = return > 0 // int Compare(T a, T b); @@ -152,13 +127,6 @@ namespace DCFApixels.DragonECS.Core.Internal IntrospectiveSort(keys, ref comparer); } public static int BinarySearch(T[] array, int index, int length, T value, ref TComparer comparer) - { - return InternalBinarySearch(array, index, length, value, ref comparer); - } - #endregion - - #region Internal - internal static int InternalBinarySearch(T[] array, int index, int length, T value, ref TComparer comparer) { Debug.Assert(array != null, "Check the arguments in the caller!"); Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!"); @@ -183,27 +151,9 @@ namespace DCFApixels.DragonECS.Core.Internal return ~lo; } + #endregion - private static void SwapIfGreater(Span keys, ref TComparer comparer, int i, int j) - { - Debug.Assert(i != j); - if (comparer.Compare(keys[i], keys[j]) > 0) - { - T key = keys[i]; - keys[i] = keys[j]; - keys[j] = key; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void Swap(Span a, int i, int j) - { - Debug.Assert(i != j); - T t = a[i]; - a[i] = a[j]; - a[j] = t; - } - + #region Internal internal static void IntrospectiveSort(Span keys, ref TComparer comparer) { //Debug.Assert(comparer != null); @@ -301,8 +251,8 @@ namespace DCFApixels.DragonECS.Core.Internal private static void HeapSort(Span keys, ref TComparer comparer) { - //Debug.Assert(comparer != null); Debug.Assert(!keys.IsEmpty); + //Debug.Assert(comparer != null); int n = keys.Length; for (int i = n >> 1; i >= 1; i--) @@ -357,5 +307,325 @@ namespace DCFApixels.DragonECS.Core.Internal } } #endregion + + #region Swaps + private static void SwapIfGreater(Span keys, ref TComparer comparer, int i, int j) + { + Debug.Assert(i != j); + if (comparer.Compare(keys[i], keys[j]) > 0) + { + T key = keys[i]; + keys[i] = keys[j]; + keys[j] = key; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Swap(Span a, int i, int j) + { + Debug.Assert(i != j); + T t = a[i]; + a[i] = a[j]; + a[j] = t; + } + #endregion } + + #region Wrappers +#if ENABLE_IL2CPP + [Il2CppSetOption(Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif + internal readonly struct ComparableWrapper : IComparer + where T : IComparable + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Compare(T x, T y) { return x.CompareTo(y); } + } +#if ENABLE_IL2CPP + [Il2CppSetOption(Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif + internal readonly struct ComparisonWrapper : IComparer + { + public readonly Comparison Comparison; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ComparisonWrapper(Comparison comparison) + { + Comparison = comparison; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Compare(T x, T y) + { + return Comparison(x, y); + } + } +#if ENABLE_IL2CPP + [Il2CppSetOption(Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif + internal readonly struct ComparerWrapper : IComparer + { + public readonly Comparer Comparer; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ComparerWrapper(Comparer comparer) + { + Comparer = comparer; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Compare(T x, T y) + { + return Comparer.Compare(x, y); + } + } + #endregion } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +//namespace DCFApixels.DragonECS.Core.Internal +//{ +// internal interface IStructComparer : IComparer +// { +// // a > b = return > 0 +// // int Compare(T a, T b); +// } +// +//#if ENABLE_IL2CPP +// [Il2CppSetOption(Option.NullChecks, false)] +// [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +//#endif +// internal static class ArraySortHalperX +// { +// private const int IntrosortSizeThreshold = 16; +// +// #region IStructComparer +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public static void SwapIfGreater(T[] items, ref TComparer comparer, int i, int j) where TComparer : IStructComparer +// { +// if (comparer.Compare(items[i], items[j]) > 0) +// { +// T key = items[i]; +// items[i] = items[j]; +// items[j] = key; +// } +// } +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public static void InsertionSort(T[] items, ref TComparer comparer) where TComparer : IStructComparer +// { +// for (int i = 0; i < items.Length - 1; i++) +// { +// T t = items[i + 1]; +// +// int j = i; +// while (j >= 0 && comparer.Compare(t, items[j]) < 0) +// { +// items[j + 1] = items[j]; +// j--; +// } +// +// items[j + 1] = t; +// } +// } +// +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public static void Sort(T[] items, ref TComparer comparer) where TComparer : IStructComparer +// { +// int length = items.Length; +// if (length == 1) +// { +// return; +// } +// +// if (length <= IntrosortSizeThreshold) +// { +// +// if (length == 2) +// { +// SwapIfGreater(items, ref comparer, 0, 1); +// return; +// } +// +// if (length == 3) +// { +// SwapIfGreater(items, ref comparer, 0, 1); +// SwapIfGreater(items, ref comparer, 0, 2); +// SwapIfGreater(items, ref comparer, 1, 2); +// return; +// } +// +// InsertionSort(items, ref comparer); +// return; +// } +// +// IStructComparer packed = comparer; +// Array.Sort(items, 0, items.Length, packed); +// comparer = (TComparer)packed; +// } +// #endregion +// +// #region Comparison +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public static void SwapIfGreater(T[] items, Comparison comparison, int i, int j) +// { +// if (comparison(items[i], items[j]) > 0) +// { +// T key = items[i]; +// items[i] = items[j]; +// items[j] = key; +// } +// } +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public static void InsertionSort(T[] items, int length, Comparison comparison) +// { +// for (int i = 0; i < length - 1; i++) +// { +// T t = items[i + 1]; +// +// int j = i; +// while (j >= 0 && comparison(t, items[j]) < 0) +// { +// items[j + 1] = items[j]; +// j--; +// } +// +// items[j + 1] = t; +// } +// } +// +//#if ENABLE_IL2CPP +// [Il2CppSetOption(Option.NullChecks, false)] +// [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +//#endif +// private class ComparisonHach : IComparer +// { +// public static readonly ComparisonHach Instance = new ComparisonHach(); +// public Comparison comparison; +// private ComparisonHach() { } +// public int Compare(T x, T y) { return comparison(x, y); } +// } +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public static void Sort(T[] items, Comparison comparison) +// { +// Sort(items, comparison, items.Length); +// } +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public static void Sort(T[] items, Comparison comparison, int length) +// { +// if (length <= IntrosortSizeThreshold) +// { +// if (length == 1) +// { +// return; +// } +// if (length == 2) +// { +// SwapIfGreater(items, comparison, 0, 1); +// return; +// } +// if (length == 3) +// { +// SwapIfGreater(items, comparison, 0, 1); +// SwapIfGreater(items, comparison, 0, 2); +// SwapIfGreater(items, comparison, 1, 2); +// return; +// } +// InsertionSort(items, length, comparison); +// return; +// } +// ComparisonHach.Instance.comparison = comparison; +// Array.Sort(items, 0, length, ComparisonHach.Instance); +// } +// #endregion +// } +// +//#if ENABLE_IL2CPP +// [Il2CppSetOption(Option.NullChecks, false)] +// [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +//#endif +// internal static unsafe class UnsafeArraySortHalperX where T : unmanaged +// { +// private const int IntrosortSizeThreshold = 16; +// +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public static void SwapIfGreater(T* items, ref TComparer comparer, int i, int j) where TComparer : IStructComparer +// { +// if (comparer.Compare(items[i], items[j]) > 0) +// { +// T key = items[i]; +// items[i] = items[j]; +// items[j] = key; +// } +// } +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// public static void InsertionSort_Unchecked(T* items, int length, ref TComparer comparer) where TComparer : IStructComparer +// { +// for (int i = 0; i < length - 1; i++) +// { +// T t = items[i + 1]; +// +// int j = i; +// while (j >= 0 && comparer.Compare(t, items[j]) < 0) +// { +// items[j + 1] = items[j]; +// j--; +// } +// +// items[j + 1] = t; +// } +// } +// public static void InsertionSort(T* items, int length, ref TComparer comparer) where TComparer : IStructComparer +// { +// if (length == 1) +// { +// return; +// } +// +// if (length == 2) +// { +// SwapIfGreater(items, ref comparer, 0, 1); +// return; +// } +// +// if (length == 3) +// { +// SwapIfGreater(items, ref comparer, 0, 1); +// SwapIfGreater(items, ref comparer, 0, 2); +// SwapIfGreater(items, ref comparer, 1, 2); +// return; +// } +// +// InsertionSort_Unchecked(items, length, ref comparer); +// } +// } +//} \ No newline at end of file diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs index 325bbe6..4bd629e 100644 --- a/src/Pools/EcsPool.cs +++ b/src/Pools/EcsPool.cs @@ -53,7 +53,7 @@ namespace DCFApixels.DragonECS #if !DRAGONECS_DISABLE_POOLS_EVENTS private StructList _listeners = new StructList(2); - private int _listenersCachedCount = 0; + private bool _hasAnyListener = false; #endif private bool _isLocked; @@ -155,7 +155,7 @@ namespace DCFApixels.DragonECS ref T result = ref _items[itemIndex]; EcsComponentLifecycle.OnAdd( _isCustomLifecycle, _customLifecycle, ref result, _worldID, entityID); #if !DRAGONECS_DISABLE_POOLS_EVENTS - _listeners.InvokeOnAddAndGet(entityID, _listenersCachedCount); + if (_hasAnyListener) { _listeners.InvokeOnAddAndGet(entityID); } #endif return ref result; } @@ -166,7 +166,7 @@ namespace DCFApixels.DragonECS if (!Has(entityID)) { EcsPoolThrowHelper.ThrowNotHaveComponent(entityID); } #endif #if !DRAGONECS_DISABLE_POOLS_EVENTS - _listeners.InvokeOnGet(entityID, _listenersCachedCount); + if (_hasAnyListener) { _listeners.InvokeOnGet(entityID); } #endif return ref _items[_mapping[entityID]]; } @@ -205,13 +205,13 @@ namespace DCFApixels.DragonECS } } _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); - EcsComponentLifecycle.OnAdd( _isCustomLifecycle, _customLifecycle, ref _items[itemIndex], _worldID, entityID); + EcsComponentLifecycle.OnAdd(_isCustomLifecycle, _customLifecycle, ref _items[itemIndex], _worldID, entityID); #if !DRAGONECS_DISABLE_POOLS_EVENTS - _listeners.InvokeOnAdd(entityID, _listenersCachedCount); + if (_hasAnyListener) { _listeners.InvokeOnAdd(entityID); } #endif } //Add block end #if !DRAGONECS_DISABLE_POOLS_EVENTS - _listeners.InvokeOnGet(entityID, _listenersCachedCount); + if (_hasAnyListener) { _listeners.InvokeOnGet(entityID); } #endif return ref _items[itemIndex]; } @@ -241,7 +241,7 @@ namespace DCFApixels.DragonECS _itemsCount--; _mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit); #if !DRAGONECS_DISABLE_POOLS_EVENTS - _listeners.InvokeOnDel(entityID, _listenersCachedCount); + if (_hasAnyListener) { _listeners.InvokeOnDel(entityID); } #endif } public void TryDel(int entityID) @@ -287,7 +287,7 @@ namespace DCFApixels.DragonECS itemIndex = 0; _mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit); #if !DRAGONECS_DISABLE_POOLS_EVENTS - _listeners.InvokeOnDel(entityID, _listenersCachedCount); + if (_hasAnyListener) { _listeners.InvokeOnDel(entityID); } #endif } _itemsCount = 0; @@ -334,14 +334,14 @@ namespace DCFApixels.DragonECS { if (listener == null) { EcsPoolThrowHelper.ThrowNullListener(); } _listeners.Add(listener); - _listenersCachedCount++; + _hasAnyListener = _listeners.Count > 0; } public void RemoveListener(IEcsPoolEventListener listener) { if (listener == null) { EcsPoolThrowHelper.ThrowNullListener(); } if (_listeners.RemoveWithOrder(listener)) { - _listenersCachedCount--; + _hasAnyListener = _listeners.Count > 0; } } #endif diff --git a/src/Pools/EcsPoolBase.cs b/src/Pools/EcsPoolBase.cs index b91b462..8aa01ef 100644 --- a/src/Pools/EcsPoolBase.cs +++ b/src/Pools/EcsPoolBase.cs @@ -296,67 +296,11 @@ namespace DCFApixels.DragonECS { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void InvokeOnAdd(this List self, int entityID) - { - self.InvokeOnAdd(entityID, self.Count); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvokeOnAdd(this List self, int entityID, int cachedCount) - { - for (int i = 0; i < cachedCount; i++) { self[i].OnAdd(entityID); } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvokeOnAddAndGet(this List self, int entityID) - { - self.InvokeOnAddAndGet(entityID, self.Count); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvokeOnAddAndGet(this List self, int entityID, int cachedCount) - { - for (int i = 0; i < cachedCount; i++) - { - self[i].OnAdd(entityID); - self[i].OnGet(entityID); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvokeOnGet(this List self, int entityID) - { - self.InvokeOnGet(entityID, self.Count); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvokeOnGet(this List self, int entityID, int cachedCount) - { - for (int i = 1; i < cachedCount; i++) { self[i].OnGet(entityID); } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvokeOnDel(this List self, int entityID) - { - self.InvokeOnDel(entityID, self.Count); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvokeOnDel(this List self, int entityID, int cachedCount) - { - for (int i = 0; i < cachedCount; i++) { self[i].OnDel(entityID); } - } - - // - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void InvokeOnAdd(ref this StructList self, int entityID) { for (int i = 0; i < self.Count; i++) { self[i].OnAdd(entityID); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void InvokeOnAdd(ref this StructList self, int entityID, int cachedCount) - { - for (int i = 0; i < cachedCount; i++) { self[i].OnAdd(entityID); } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void InvokeOnAddAndGet(ref this StructList self, int entityID) + public static void InvokeOnAddAndGet(this List self, int entityID) { for (int i = 0; i < self.Count; i++) { @@ -365,34 +309,43 @@ namespace DCFApixels.DragonECS } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void InvokeOnAddAndGet(ref this StructList self, int entityID, int cachedCount) + public static void InvokeOnGet(this List self, int entityID) { - for (int i = 0; i < cachedCount; i++) + for (int i = 1; i < self.Count; i++) { self[i].OnGet(entityID); } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void InvokeOnDel(this List self, int entityID) + { + for (int i = 0; i < self.Count; i++) { self[i].OnDel(entityID); } + } + + // + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void InvokeOnAdd(this StructList self, int entityID) + { + for (int i = 0; i < self.Count; i++) { self[i].OnAdd(entityID); } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void InvokeOnAddAndGet(this StructList self, int entityID) + { + for (int i = 0; i < self.Count; i++) { self[i].OnAdd(entityID); self[i].OnGet(entityID); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void InvokeOnGet(ref this StructList self, int entityID) + internal static void InvokeOnGet(this StructList self, int entityID) { - for (int i = 1; i < self.Count; i++) { self[i].OnGet(entityID); } + for (int i = 0; i < self.Count; i++) { self[i].OnGet(entityID); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void InvokeOnGet(ref this StructList self, int entityID, int cachedCount) - { - for (int i = 1; i < cachedCount; i++) { self[i].OnGet(entityID); } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void InvokeOnDel(ref this StructList self, int entityID) + internal static void InvokeOnDel(this StructList self, int entityID) { for (int i = 0; i < self.Count; i++) { self[i].OnDel(entityID); } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void InvokeOnDel(ref this StructList self, int entityID, int cachedCount) - { - for (int i = 0; i < cachedCount; i++) { self[i].OnDel(entityID); } - } } #endif #endregion diff --git a/src/Pools/EcsTagPool.cs b/src/Pools/EcsTagPool.cs index 07e5713..9517938 100644 --- a/src/Pools/EcsTagPool.cs +++ b/src/Pools/EcsTagPool.cs @@ -44,7 +44,7 @@ namespace DCFApixels.DragonECS #if !DRAGONECS_DISABLE_POOLS_EVENTS private StructList _listeners = new StructList(2); - private int _listenersCachedCount = 0; + private bool _hasAnyListener = false; #endif private bool _isLocked; @@ -127,7 +127,7 @@ namespace DCFApixels.DragonECS _mapping[entityID] = true; _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); #if !DRAGONECS_DISABLE_POOLS_EVENTS - _listeners.InvokeOnAdd(entityID, _listenersCachedCount); + if (_hasAnyListener) { _listeners.InvokeOnAdd(entityID); } #endif } public void TryAdd(int entityID) @@ -155,7 +155,7 @@ namespace DCFApixels.DragonECS _count--; _mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit); #if !DRAGONECS_DISABLE_POOLS_EVENTS - _listeners.InvokeOnDel(entityID, _listenersCachedCount); + if (_hasAnyListener) { _listeners.InvokeOnDel(entityID); } #endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -225,7 +225,7 @@ namespace DCFApixels.DragonECS _mapping[entityID] = false; _mediator.UnregisterComponent(entityID, _componentTypeID, _maskBit); #if !DRAGONECS_DISABLE_POOLS_EVENTS - _listeners.InvokeOnDel(entityID, _listenersCachedCount); + if (_hasAnyListener) { _listeners.InvokeOnDel(entityID); } #endif } } @@ -295,14 +295,14 @@ namespace DCFApixels.DragonECS { if (listener == null) { EcsPoolThrowHelper.ThrowNullListener(); } _listeners.Add(listener); - _listenersCachedCount++; + _hasAnyListener = _listeners.Count > 0; } public void RemoveListener(IEcsPoolEventListener listener) { if (listener == null) { EcsPoolThrowHelper.ThrowNullListener(); } if (_listeners.RemoveWithOrder(listener)) { - _listenersCachedCount--; + _hasAnyListener = _listeners.Count > 0; } } #endif