diff --git a/DragonECS.csproj b/DragonECS.csproj
index 41358e5..ab300ab 100644
--- a/DragonECS.csproj
+++ b/DragonECS.csproj
@@ -10,7 +10,7 @@
DCFApixels.DragonECS
DragonECS
- 0.9.9
+ 0.9.10
DCFApixels
ECS Framework for Game Engines with C# and .Net Platform
DCFApixels
diff --git a/package.json b/package.json
index fcffa56..bc71101 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"displayName": "DragonECS",
"description": "C# Entity Component System Framework",
"unity": "2020.3",
- "version": "0.9.9",
+ "version": "0.9.10",
"repository": {
"type": "git",
"url": "https://github.com/DCFApixels/DragonECS.git"
diff --git a/src/Collections/EcsGroup.cs b/src/Collections/EcsGroup.cs
index 5d70cfe..997b4ce 100644
--- a/src/Collections/EcsGroup.cs
+++ b/src/Collections/EcsGroup.cs
@@ -1,6 +1,7 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
+using DCFApixels.DragonECS.Core.Unchecked;
using DCFApixels.DragonECS.Internal;
using System;
using System.Collections;
diff --git a/src/Collections/EcsSpan.cs b/src/Collections/EcsSpan.cs
index 48c26c4..11161e6 100644
--- a/src/Collections/EcsSpan.cs
+++ b/src/Collections/EcsSpan.cs
@@ -1,6 +1,7 @@
#if DISABLE_DEBUG
#undef DEBUG
#endif
+using DCFApixels.DragonECS.Core.Unchecked;
using DCFApixels.DragonECS.Internal;
using System;
using System.Collections.Generic;
diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs
index baecc2e..1810d02 100644
--- a/src/EcsWorld.cs
+++ b/src/EcsWorld.cs
@@ -2,6 +2,7 @@
#undef DEBUG
#endif
using DCFApixels.DragonECS.Core;
+using DCFApixels.DragonECS.Core.Unchecked;
using DCFApixels.DragonECS.Internal;
using DCFApixels.DragonECS.PoolsCore;
using System;
diff --git a/src/Pools/EcsPool.cs b/src/Pools/EcsPool.cs
index 0780c60..68b70af 100644
--- a/src/Pools/EcsPool.cs
+++ b/src/Pools/EcsPool.cs
@@ -101,6 +101,7 @@ namespace DCFApixels.DragonECS
{
ref int itemIndex = ref _mapping[entityID];
#if DEBUG
+ if (entityID == EcsConsts.NULL_ENTITY_ID) { Throw.Ent_ThrowIsNotAlive(_source, entityID); }
if (_source.IsUsed(entityID) == false) { Throw.Ent_ThrowIsNotAlive(_source, entityID); }
if (itemIndex > 0) { EcsPoolThrowHelper.ThrowAlreadyHasComponent(entityID); }
if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); }
@@ -158,6 +159,9 @@ namespace DCFApixels.DragonECS
//}
+#if DEBUG
+ if (entityID == EcsConsts.NULL_ENTITY_ID) { Throw.Ent_ThrowIsNotAlive(_source, entityID); }
+#endif
ref int itemIndex = ref _mapping[entityID];
if (itemIndex <= 0)
{ //Add block
@@ -197,6 +201,7 @@ namespace DCFApixels.DragonECS
{
ref int itemIndex = ref _mapping[entityID];
#if DEBUG
+ if (entityID == EcsConsts.NULL_ENTITY_ID) { Throw.Ent_ThrowIsNotAlive(_source, entityID); }
if (itemIndex <= 0) { EcsPoolThrowHelper.ThrowNotHaveComponent(entityID); }
if (_isLocked) { EcsPoolThrowHelper.ThrowPoolLocked(); }
#elif DRAGONECS_STABILITY_MODE
@@ -254,8 +259,8 @@ namespace DCFApixels.DragonECS
#elif DRAGONECS_STABILITY_MODE
if (_isLocked) { return; }
#endif
+ _recycledItemsCount = 0; // ������� ����� ����������, ��� ��� Del �� ��������
if (_itemsCount <= 0) { return; }
- _itemsCount = 0;
var span = _source.Where(out SingleAspect _);
foreach (var entityID in span)
{
@@ -267,6 +272,8 @@ namespace DCFApixels.DragonECS
_listeners.InvokeOnDel(entityID, _listenersCachedCount);
#endif
}
+ _itemsCount = 0;
+ _recycledItemsCount = 0;
}
#endregion
diff --git a/src/Utils/Uncheked.meta b/src/Utils/Uncheked.meta
new file mode 100644
index 0000000..af73cfd
--- /dev/null
+++ b/src/Utils/Uncheked.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 5f2e943735300fe40bdbff86b6089dad
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/src/Utils/Uncheked/EntitiesMatrix.cs b/src/Utils/Uncheked/EntitiesMatrix.cs
new file mode 100644
index 0000000..75baf56
--- /dev/null
+++ b/src/Utils/Uncheked/EntitiesMatrix.cs
@@ -0,0 +1,44 @@
+#if DISABLE_DEBUG
+#undef DEBUG
+#endif
+
+namespace DCFApixels.DragonECS.UncheckedCore
+{
+ public readonly struct EntitiesMatrix
+ {
+ private readonly EcsWorld _world;
+ public EntitiesMatrix(EcsWorld world)
+ {
+ _world = world;
+ }
+ public int PoolsCount
+ {
+ get { return _world.PoolsCount; }
+ }
+ public int EntitesCount
+ {
+ get { return _world.Capacity; }
+ }
+ public int GetEntityComponentsCount(int entityID)
+ {
+ return _world.GetComponentsCount(entityID);
+ }
+ public int GetEntityGen(int entityID)
+ {
+ return _world.GetGen(entityID);
+ }
+ public bool IsEntityUsed(int entityID)
+ {
+ return _world.IsUsed(entityID);
+ }
+ public bool this[int entityID, int poolID]
+ {
+ get
+ {
+ int entityStartChunkIndex = entityID << _world._entityComponentMaskLengthBitShift;
+ var chunkInfo = EcsMaskChunck.FromID(poolID);
+ return (_world._entityComponentMasks[entityStartChunkIndex + chunkInfo.chunkIndex] & chunkInfo.mask) != 0;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Utils/Uncheked/EntitiesMatrix.cs.meta b/src/Utils/Uncheked/EntitiesMatrix.cs.meta
new file mode 100644
index 0000000..3f9b8a8
--- /dev/null
+++ b/src/Utils/Uncheked/EntitiesMatrix.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 82a4a05728fb81b4b903d9893a85f77f
\ No newline at end of file
diff --git a/src/Utils/Uncheked/EntitySlotInfo.cs b/src/Utils/Uncheked/EntitySlotInfo.cs
new file mode 100644
index 0000000..942d666
--- /dev/null
+++ b/src/Utils/Uncheked/EntitySlotInfo.cs
@@ -0,0 +1,137 @@
+#if DISABLE_DEBUG
+#undef DEBUG
+#endif
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace DCFApixels.DragonECS.Core.Unchecked
+{
+ [StructLayout(LayoutKind.Explicit, Pack = 2, Size = 8)]
+ [DebuggerTypeProxy(typeof(EntityDebuggerProxy))]
+ public struct EntitySlotInfo : IEquatable
+ {
+#if UNITY_EDITOR
+ [UnityEngine.SerializeField]
+#endif
+ [FieldOffset(0)]
+ public long full; //Union
+ [FieldOffset(0), NonSerialized]
+ public int id;
+ [FieldOffset(4), NonSerialized]
+ public short gen;
+ [FieldOffset(6), NonSerialized]
+ public short worldID;
+
+ #region Properties
+ public EcsWorld World { get { return EcsWorld.GetWorld(worldID); } }
+ public StateFlag State { get { return full == 0 ? StateFlag.Null : World.IsAlive(id, gen) ? StateFlag.Alive : StateFlag.Dead; } }
+ #endregion
+
+ #region Constructors/Deconstructors
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public EntitySlotInfo(long full) : this()
+ {
+ this.full = full;
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public EntitySlotInfo(int id, short gen, short world) : this()
+ {
+ this.id = id;
+ this.gen = gen;
+ worldID = world;
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Deconstruct(out int id, out int gen, out int worldID)
+ {
+ id = this.id;
+ gen = this.gen;
+ worldID = this.worldID;
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void Deconstruct(out int id, out int worldID)
+ {
+ id = this.id;
+ worldID = this.worldID;
+ }
+ #endregion
+
+ #region Operators
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator ==(EntitySlotInfo a, EntitySlotInfo b) { return a.full == b.full; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool operator !=(EntitySlotInfo a, EntitySlotInfo b) { return a.full != b.full; }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static explicit operator EntitySlotInfo(entlong a) { return new EntitySlotInfo(a._full); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static explicit operator entlong(EntitySlotInfo a) { return new entlong(a.full); }
+ #endregion
+
+ #region Other
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override int GetHashCode() { return unchecked(id ^ gen ^ (worldID * EcsConsts.MAGIC_PRIME)); }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override string ToString() { return $"slot(id:{id} g:{gen} w:{worldID} {(State == StateFlag.Null ? "null" : State == StateFlag.Alive ? "alive" : "not alive")})"; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override bool Equals(object obj) { return obj is EntitySlotInfo other && this == other; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool Equals(EntitySlotInfo other) { return this == other; }
+
+ public enum StateFlag { Null, Dead, Alive, }
+ #endregion
+ }
+
+
+
+ internal class EntityDebuggerProxy
+ {
+ private List