title: connect systems with events
body: <p>Using the Entity-Component-System pattern I want to connect some systems with events. So some systems shouldn't run in a loop, they should just run on demand.</p>
  
  <p>Given the example of a <em>Health</em> system a <em>Death</em> system should only run when a component gets below 1 health.</p>
  
  <p>I thought about having two types of systems. The first type is a periodic system. This runs once per frame, for example a <em>Render</em> or <em>Movement</em> System. The other type is an event based system. As mentioned before a connection between <em>Health</em> and <em>Death</em>.</p>
  
  <p>First I created a basic interface used by both system types.</p>
  
  <pre><code>internal interface ISystem
  {
      List&lt;Guid&gt; EntityCache { get; } // Only relevant entities get stored in there
  
      ComponentRequirements ComponentRequirements { get; } // the required components for this system
  
      void InitComponentRequirements();
  
      void InitComponentPools(EntityManager entityManager);
  
      void UpdateCacheEntities(); // update all entities from the cache
  
      void UpdateCacheEntity(Guid cacheEntityId); // update a single entity from the cache
  }
  </code></pre>
  
  <p>Further I created the interfaces </p>
  
  <pre><code>internal interface IReactiveSystem : ISystem
  {
  // event based
  }
  </code></pre>
  
  <p>and</p>
  
  <pre><code>internal interface IPeriodicSystem : ISystem
  {
  // runs in a loop
  }
  </code></pre>
  
  <p>but I'm not sure if they will be necessary. There is no problem using</p>
  
  <pre><code>foreach (ISystem system in entityManager.Systems)
  {
      system.UpdateCacheEntities();
  }
  </code></pre>
  
  <p>but I don't want to run a system if not needed.</p>
  
  <p>There are two types of Events, a <code>ChangeEvent</code> and a <code>ExecuteEvent</code>. The first gets triggered when a value from a component has changed. The second one gets triggered when something should be done with a specific entity.</p>
  
  <p>If you Need or want to you can have a look at the <code>EntityManager</code></p>
  
  <p><a href="https://pastebin.com/NnfBc0N9" rel="nofollow noreferrer">https://pastebin.com/NnfBc0N9</a></p>
  
  <p>the <code>ComponentRequirements</code></p>
  
  <p><a href="https://pastebin.com/xt3YGVSv" rel="nofollow noreferrer">https://pastebin.com/xt3YGVSv</a></p>
  
  <p>and the usage of the ECS</p>
  
  <p><a href="https://pastebin.com/Yuze72xf" rel="nofollow noreferrer">https://pastebin.com/Yuze72xf</a></p>
  
  <p>An example System would be something like this</p>
  
  <pre><code>internal class HealthSystem : IReactiveSystem
  {
      public HealthSystem(EntityManager entityManager)
      {
          InitComponentRequirements();
          InitComponentPools(entityManager);
      }
  
      private Dictionary&lt;Guid, HealthComponent&gt; healthComponentPool;
  
      public List&lt;Guid&gt; EntityCache { get; } = new List&lt;Guid&gt;();
  
      public ComponentRequirements ComponentRequirements { get; } = new ComponentRequirements();
  
      public void InitComponentRequirements()
      {
          ComponentRequirements.AddRequiredType&lt;HealthComponent&gt;();
      }
  
      public void InitComponentPools(EntityManager entityManager)
      {
          healthComponentPool = entityManager.GetComponentPoolByType&lt;HealthComponent&gt;();
      }
  
      public void UpdateCacheEntities()
      {
          for (int i = 0; i &lt; EntityCache.Count; i++)
          {
              UpdateCacheEntity(EntityCache[i]);
          }
      }
  
      public void UpdateCacheEntity(Guid cacheEntityId)
      {
          Health healthComponent = healthComponentPool[cacheEntityId];
          healthComponent.Value += 10; // just some tests
          // update UI 
      }
  }
  </code></pre>
  
  <p>How can I create <code>ChangeEvents</code> and <code>ExecuteEvents</code> for the different systems?</p>
  
  <hr>
  
  <p><strong>EDIT</strong></p>
  
  <p>Is there a way to add event delegates to the components to run a specific system for this entity on change if a change event is listening or on demand if an execute event is listening?</p>
  
  <p>By mentioning <code>ChangeEvent</code> and <code>ExecuteEvent</code> I just mean event delegates.</p>
  
  <p>Currently I could do something like this</p>
  
  <pre><code>internal class HealthSystem : IReactiveSystem
  {
      //… other stuff
  
      IReactiveSystem deathSystem = entityManager.GetSystem&lt;Death&gt;(); // Get a system by its type
  
      public void UpdateCacheEntity(Guid cacheEntityId)
      {
          // Change Health component
          // Update UI
  
          if(currentHealth &lt; 1) // call the death system if the entity will be dead
          {
              deathSystem.UpdateCacheEntity(cacheEntityId);
          }
      }
  }
  </code></pre>
  
  <p>But I was hoping to achieve a better architecture by using event delegates to make systems communicate and share data between each other.</p>