EntityManager.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Specialized;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using Microsoft.Xna.Framework;
  7. using MonoGame.Extended.Collections;
  8. using MonoGame.Extended.ECS.Systems;
  9. namespace MonoGame.Extended.ECS
  10. {
  11. public class EntityManager : UpdateSystem
  12. {
  13. private const int _defaultBagSize = 128;
  14. public EntityManager(ComponentManager componentManager)
  15. {
  16. _componentManager = componentManager;
  17. _addedEntities = new Bag<int>(_defaultBagSize);
  18. _removedEntities = new Bag<int>(_defaultBagSize);
  19. _changedEntities = new Bag<int>(_defaultBagSize);
  20. _entityToComponentBits = new Bag<BitVector32>(_defaultBagSize);
  21. _componentManager.ComponentsChanged += OnComponentsChanged;
  22. _entityBag = new Bag<Entity>(_defaultBagSize);
  23. _entityPool = new Pool<Entity>(() => new Entity(_nextId++, this, _componentManager), _defaultBagSize);
  24. }
  25. private readonly ComponentManager _componentManager;
  26. private int _nextId;
  27. public int Capacity => _entityBag.Capacity;
  28. public IEnumerable<int> Entities => _entityBag.Where(e => e != null).Select(e => e.Id);
  29. public int ActiveCount { get; private set; }
  30. private readonly Bag<Entity> _entityBag;
  31. private readonly Pool<Entity> _entityPool;
  32. private readonly Bag<int> _addedEntities;
  33. private readonly Bag<int> _removedEntities;
  34. private readonly Bag<int> _changedEntities;
  35. private readonly Bag<BitVector32> _entityToComponentBits;
  36. public event Action<int> EntityAdded;
  37. public event Action<int> EntityRemoved;
  38. public event Action<int> EntityChanged;
  39. public Entity Create()
  40. {
  41. var entity = _entityPool.Obtain();
  42. var id = entity.Id;
  43. Debug.Assert(_entityBag[id] == null);
  44. _entityBag[id] = entity;
  45. _addedEntities.Add(id);
  46. _entityToComponentBits[id] = new BitVector32(0);
  47. return entity;
  48. }
  49. public void Destroy(int entityId)
  50. {
  51. if (!_removedEntities.Contains(entityId))
  52. _removedEntities.Add(entityId);
  53. }
  54. public void Destroy(Entity entity)
  55. {
  56. Destroy(entity.Id);
  57. }
  58. public Entity Get(int entityId)
  59. {
  60. return _entityBag[entityId];
  61. }
  62. public BitVector32 GetComponentBits(int entityId)
  63. {
  64. return _entityToComponentBits[entityId];
  65. }
  66. private void OnComponentsChanged(int entityId)
  67. {
  68. _changedEntities.Add(entityId);
  69. _entityToComponentBits[entityId] = _componentManager.CreateComponentBits(entityId);
  70. EntityChanged?.Invoke(entityId);
  71. }
  72. public override void Update(GameTime gameTime)
  73. {
  74. foreach (var entityId in _addedEntities)
  75. {
  76. _entityToComponentBits[entityId] = _componentManager.CreateComponentBits(entityId);
  77. ActiveCount++;
  78. EntityAdded?.Invoke(entityId);
  79. }
  80. foreach (var entityId in _changedEntities)
  81. {
  82. _entityToComponentBits[entityId] = _componentManager.CreateComponentBits(entityId);
  83. EntityChanged?.Invoke(entityId);
  84. }
  85. foreach (var entityId in _removedEntities)
  86. {
  87. // we must notify subscribers before removing it from the pool
  88. // otherwise an entity system could still be using the entity when the same id is obtained.
  89. EntityRemoved?.Invoke(entityId);
  90. var entity = _entityBag[entityId];
  91. _entityBag[entityId] = null;
  92. _componentManager.Destroy(entityId);
  93. _entityToComponentBits[entityId] = default(BitVector32);
  94. ActiveCount--;
  95. _entityPool.Free(entity);
  96. }
  97. _addedEntities.Clear();
  98. _removedEntities.Clear();
  99. _changedEntities.Clear();
  100. }
  101. }
  102. }