create references to objects and hold these references in a cache












1















I would like to create a chache for each system in my Entity-Component-System. Currently each system would loop through all entities and check for required components.



internal class MySystem : ISystem
{
public void Run()
{
for (int i = 0; i < EntityManager.activeEntities.Count; i++)
{
Guid entityId = EntityManager.activeEntities[i];

if (EntityManager.GetComponentPool<Position>().TryGetValue(entityId, out Position positionComponent)) // Get the position component
{
// Update the position of the entity
}
}
}
}


ISystem just requires to implement a Run method. I think this approach might get really slow if each system has to check for the right components.



I save all the components to a pool of the component type and these pools get stored to a collection.



private Dictionary<Type, object> componentPools = new Dictionary<Type, object>();


where object of Dictionary<Type, object> is always Dictionary<Guid, TComponent>().



When running a system it would be better passing in a collection of the required components only.



These are the methods from my EntityManager class that would affect the cache of each system



    public Guid CreateEntity()
{
// Add and return entityID
}

public void DestroyEntity(Guid entityId)
{
// Remove entity by ID

// Remove all components from all pools by refering to the entityID
}

public void AddComponentToEntity<TComponent>(Guid entityId, IComponent component) where TComponent : IComponent
{
// Add the component to the component pool by refering to the entityID
}

public void RemoveComponentFromEntity<TComponent>(Guid entityId) where TComponent : IComponent
{
// Remove the component from the component pool by refering to the entityID
}

public void AddComponentPool<TComponent>() where TComponent : IComponent
{
// Add a new component pool by its type
}

public void RemoveComponentPool<TComponent>() where TComponent : IComponent
{
// Remove a component pool by its type
}


How can I create systems that refer to the required components only and update their cache when calling one of these methods shown above?



I tried to create a pseudo code example to show what I mean



internal class Movement : ISystem
{
// Just add entities with a Position and a MovementSpeed component
List<Guid> cacheEntities = new List<Guid>();

public void Run()
{
for (int i = 0; i < cacheEntities.Count; i++)
{
Guid entityId = cacheEntities[i];

Position positionComponent = EntityManager.GetComponentPool<Position>()[entityId];
MovementSpeed movementSpeedComponent = EntityManager.GetComponentPool<MovementSpeed>()[entityId];

// Move
}
}
}


and maybe it's possible to create collections that require no entityId, so they only store the reference to the component that should get updated.










share|improve this question



























    1















    I would like to create a chache for each system in my Entity-Component-System. Currently each system would loop through all entities and check for required components.



    internal class MySystem : ISystem
    {
    public void Run()
    {
    for (int i = 0; i < EntityManager.activeEntities.Count; i++)
    {
    Guid entityId = EntityManager.activeEntities[i];

    if (EntityManager.GetComponentPool<Position>().TryGetValue(entityId, out Position positionComponent)) // Get the position component
    {
    // Update the position of the entity
    }
    }
    }
    }


    ISystem just requires to implement a Run method. I think this approach might get really slow if each system has to check for the right components.



    I save all the components to a pool of the component type and these pools get stored to a collection.



    private Dictionary<Type, object> componentPools = new Dictionary<Type, object>();


    where object of Dictionary<Type, object> is always Dictionary<Guid, TComponent>().



    When running a system it would be better passing in a collection of the required components only.



    These are the methods from my EntityManager class that would affect the cache of each system



        public Guid CreateEntity()
    {
    // Add and return entityID
    }

    public void DestroyEntity(Guid entityId)
    {
    // Remove entity by ID

    // Remove all components from all pools by refering to the entityID
    }

    public void AddComponentToEntity<TComponent>(Guid entityId, IComponent component) where TComponent : IComponent
    {
    // Add the component to the component pool by refering to the entityID
    }

    public void RemoveComponentFromEntity<TComponent>(Guid entityId) where TComponent : IComponent
    {
    // Remove the component from the component pool by refering to the entityID
    }

    public void AddComponentPool<TComponent>() where TComponent : IComponent
    {
    // Add a new component pool by its type
    }

    public void RemoveComponentPool<TComponent>() where TComponent : IComponent
    {
    // Remove a component pool by its type
    }


    How can I create systems that refer to the required components only and update their cache when calling one of these methods shown above?



    I tried to create a pseudo code example to show what I mean



    internal class Movement : ISystem
    {
    // Just add entities with a Position and a MovementSpeed component
    List<Guid> cacheEntities = new List<Guid>();

    public void Run()
    {
    for (int i = 0; i < cacheEntities.Count; i++)
    {
    Guid entityId = cacheEntities[i];

    Position positionComponent = EntityManager.GetComponentPool<Position>()[entityId];
    MovementSpeed movementSpeedComponent = EntityManager.GetComponentPool<MovementSpeed>()[entityId];

    // Move
    }
    }
    }


    and maybe it's possible to create collections that require no entityId, so they only store the reference to the component that should get updated.










    share|improve this question

























      1












      1








      1


      1






      I would like to create a chache for each system in my Entity-Component-System. Currently each system would loop through all entities and check for required components.



      internal class MySystem : ISystem
      {
      public void Run()
      {
      for (int i = 0; i < EntityManager.activeEntities.Count; i++)
      {
      Guid entityId = EntityManager.activeEntities[i];

      if (EntityManager.GetComponentPool<Position>().TryGetValue(entityId, out Position positionComponent)) // Get the position component
      {
      // Update the position of the entity
      }
      }
      }
      }


      ISystem just requires to implement a Run method. I think this approach might get really slow if each system has to check for the right components.



      I save all the components to a pool of the component type and these pools get stored to a collection.



      private Dictionary<Type, object> componentPools = new Dictionary<Type, object>();


      where object of Dictionary<Type, object> is always Dictionary<Guid, TComponent>().



      When running a system it would be better passing in a collection of the required components only.



      These are the methods from my EntityManager class that would affect the cache of each system



          public Guid CreateEntity()
      {
      // Add and return entityID
      }

      public void DestroyEntity(Guid entityId)
      {
      // Remove entity by ID

      // Remove all components from all pools by refering to the entityID
      }

      public void AddComponentToEntity<TComponent>(Guid entityId, IComponent component) where TComponent : IComponent
      {
      // Add the component to the component pool by refering to the entityID
      }

      public void RemoveComponentFromEntity<TComponent>(Guid entityId) where TComponent : IComponent
      {
      // Remove the component from the component pool by refering to the entityID
      }

      public void AddComponentPool<TComponent>() where TComponent : IComponent
      {
      // Add a new component pool by its type
      }

      public void RemoveComponentPool<TComponent>() where TComponent : IComponent
      {
      // Remove a component pool by its type
      }


      How can I create systems that refer to the required components only and update their cache when calling one of these methods shown above?



      I tried to create a pseudo code example to show what I mean



      internal class Movement : ISystem
      {
      // Just add entities with a Position and a MovementSpeed component
      List<Guid> cacheEntities = new List<Guid>();

      public void Run()
      {
      for (int i = 0; i < cacheEntities.Count; i++)
      {
      Guid entityId = cacheEntities[i];

      Position positionComponent = EntityManager.GetComponentPool<Position>()[entityId];
      MovementSpeed movementSpeedComponent = EntityManager.GetComponentPool<MovementSpeed>()[entityId];

      // Move
      }
      }
      }


      and maybe it's possible to create collections that require no entityId, so they only store the reference to the component that should get updated.










      share|improve this question














      I would like to create a chache for each system in my Entity-Component-System. Currently each system would loop through all entities and check for required components.



      internal class MySystem : ISystem
      {
      public void Run()
      {
      for (int i = 0; i < EntityManager.activeEntities.Count; i++)
      {
      Guid entityId = EntityManager.activeEntities[i];

      if (EntityManager.GetComponentPool<Position>().TryGetValue(entityId, out Position positionComponent)) // Get the position component
      {
      // Update the position of the entity
      }
      }
      }
      }


      ISystem just requires to implement a Run method. I think this approach might get really slow if each system has to check for the right components.



      I save all the components to a pool of the component type and these pools get stored to a collection.



      private Dictionary<Type, object> componentPools = new Dictionary<Type, object>();


      where object of Dictionary<Type, object> is always Dictionary<Guid, TComponent>().



      When running a system it would be better passing in a collection of the required components only.



      These are the methods from my EntityManager class that would affect the cache of each system



          public Guid CreateEntity()
      {
      // Add and return entityID
      }

      public void DestroyEntity(Guid entityId)
      {
      // Remove entity by ID

      // Remove all components from all pools by refering to the entityID
      }

      public void AddComponentToEntity<TComponent>(Guid entityId, IComponent component) where TComponent : IComponent
      {
      // Add the component to the component pool by refering to the entityID
      }

      public void RemoveComponentFromEntity<TComponent>(Guid entityId) where TComponent : IComponent
      {
      // Remove the component from the component pool by refering to the entityID
      }

      public void AddComponentPool<TComponent>() where TComponent : IComponent
      {
      // Add a new component pool by its type
      }

      public void RemoveComponentPool<TComponent>() where TComponent : IComponent
      {
      // Remove a component pool by its type
      }


      How can I create systems that refer to the required components only and update their cache when calling one of these methods shown above?



      I tried to create a pseudo code example to show what I mean



      internal class Movement : ISystem
      {
      // Just add entities with a Position and a MovementSpeed component
      List<Guid> cacheEntities = new List<Guid>();

      public void Run()
      {
      for (int i = 0; i < cacheEntities.Count; i++)
      {
      Guid entityId = cacheEntities[i];

      Position positionComponent = EntityManager.GetComponentPool<Position>()[entityId];
      MovementSpeed movementSpeedComponent = EntityManager.GetComponentPool<MovementSpeed>()[entityId];

      // Move
      }
      }
      }


      and maybe it's possible to create collections that require no entityId, so they only store the reference to the component that should get updated.







      c# entity-component-system






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 17 at 8:30









      MHComputechMHComputech

      26213




      26213
























          1 Answer
          1






          active

          oldest

          votes


















          1





          +100









          The Entity-components-system asks for a specific design.




          ECS follows the composition over inheritance principle




          Dealing with pools of components, which are in essence raw data, it makes sense to handle this data with reference to the actual component type -- given you'll want to apply specific behaviors for each.



          The decorator pattern plays nicely with composition, adding behaviors by wrapping types. It also allows EntityManager to delegate responsibilities to the component pools, instead of having one massive decision tree that has to handle all cases.



          Let's implement an example.




          Suppose there is a drawing function. This would be a "System" that iterates through all entities that have both a physical and a visible component, and draws them. The visible component could typically have some information about how an entity should look (e.g. human, monster, sparks flying around, flying arrow), and use the physical component to know where to draw it.





          1. Entity.cs



          An entity will be typically made up of an ID and a list of components that are attached to it.




          class Entity
          {
          public Entity(Guid entityId)
          {
          EntityId = entityId;
          Components = new List<IComponent>();
          }

          public Guid EntityId { get; }
          public List<IComponent> Components { get; }
          }



          1. Component.cs


          Starting with the marker interface.



          interface IComponent { }

          enum Appearance : byte
          {
          Human,
          Monster,
          SparksFlyingAround,
          FlyingArrow
          }

          class VisibleComponent : IComponent
          {
          public Appearance Appearance { get; set; }
          }

          class PhysicalComponent : IComponent
          {
          public double X { get; set; }
          public double Y { get; set; }
          }



          1. System.cs


          Adding a collection for the SystemEntities.



          interface ISystem
          {
          ISet<Guid> SystemEntities { get; }
          Type ComponentTypes { get; }

          void Run();
          }

          class DrawingSystem : ISystem
          {
          public DrawingSystem(params Type componentTypes)
          {
          ComponentTypes = componentTypes;
          SystemEntities = new HashSet<Guid>();
          }

          public ISet<Guid> SystemEntities { get; }

          public Type ComponentTypes { get; }

          public void Run()
          {
          foreach (var entity in SystemEntities)
          {
          Draw(entity);
          }
          }

          private void Draw(Guid entity) { /*Do Magic*/ }
          }



          1. ComponentPool.cs


          Next, we'll lay the ground work for what's to come. Our component pools should also have a non-generic interface, that we can fall back upon when we can't supply a component type.



          interface IComponentPool
          {
          void RemoveEntity(Guid entityId);
          bool ContainsEntity(Guid entityId);
          }

          interface IComponentPool<T> : IComponentPool
          {
          void AddEntity(Guid entityId, T component);
          }

          class ComponentPool<T> : IComponentPool<T>
          {
          private Dictionary<Guid, T> component = new Dictionary<Guid, T>();

          public void AddEntity(Guid entityId, T component)
          {
          this.component.Add(entityId, component);
          }

          public void RemoveEntity(Guid entityId)
          {
          component.Remove(entityId);
          }

          public bool ContainsEntity(Guid entityId)
          {
          return component.ContainsKey(entityId);
          }
          }


          Next step is the pool decorator. The decorator pattern is implemented by exposing the same interface as the class it wraps, applying any desired behavior in the process. In our case, we want to check if added entities posses all the component types a system requires. And if they do, add them to the collection.



          class PoolDecorator<T> : IComponentPool<T>
          {
          private readonly IComponentPool<T> wrappedPool;
          private readonly EntityManager entityManager;
          private readonly ISystem system;

          public PoolDecorator(IComponentPool<T> componentPool, EntityManager entityManager, ISystem system)
          {
          this.wrappedPool = componentPool;
          this.entityManager = entityManager;
          this.system = system;
          }

          public void AddEntity(Guid entityId, T component)
          {
          wrappedPool.AddEntity(entityId, component);

          if (system.ComponentTypes
          .Select(t => entityManager.GetComponentPool(t))
          .All(p => p.ContainsEntity(entityId)))
          {
          system.SystemEntities.Add(entityId);
          }
          }

          public void RemoveEntity(Guid entityId)
          {
          wrappedPool.RemoveEntity(entityId);
          system.SystemEntities.Remove(entityId);
          }

          public bool ContainsEntity(Guid entityId)
          {
          return wrappedPool.ContainsEntity(entityId);
          }
          }


          As said, you could place the burden of checking, and managing the system collections, on EntityManager. But our current design tends to diminish complexity and provide more flexibility in the long run. Just wrap a pool once for each system it belongs to. If the system requires non default behavior, then you can create a new decorator specialized for that system -- without interfering with other systems.




          1. EntityManager.cs


          The orchestrator (aka mediator, controller,...)



          class EntityManager
          {
          List<ISystem> systems;
          Dictionary<Type, object> componentPools;

          public EntityManager()
          {
          systems = new List<ISystem>();
          componentPools = new Dictionary<Type, object>();
          ActiveEntities = new HashSet<Guid>();
          }

          public ISet<Guid> ActiveEntities { get; }

          public Guid CreateEntity()
          {
          Guid entityId;
          do entityId = Guid.NewGuid();
          while (!ActiveEntities.Add(entityId));

          return entityId;
          }

          public void DestroyEntity(Guid entityId)
          {
          componentPools.Values.Select(kp => (IComponentPool)kp).ToList().ForEach(c => c.RemoveEntity(entityId));
          systems.ForEach(c => c.SystemEntities.Remove(entityId));
          ActiveEntities.Remove(entityId);
          }

          public void AddSystems(params ISystem system)
          {
          systems.AddRange(systems);
          }

          public IComponentPool GetComponentPool(Type componentType)
          {
          return (IComponentPool)componentPools[componentType];
          }

          public IComponentPool<TComponent> GetComponentPool<TComponent>() where TComponent : IComponent
          {
          return (IComponentPool<TComponent>)componentPools[typeof(TComponent)];
          }

          public void AddComponentPool<TComponent>(IComponentPool<TComponent> componentPool) where TComponent : IComponent
          {
          componentPools.Add(typeof(TComponent), componentPool);
          }

          public void AddComponentToEntity<TComponent>(Guid entityId, TComponent component) where TComponent : IComponent
          {
          var pool = GetComponentPool<TComponent>();
          pool.AddEntity(entityId, component);
          }

          public void RemoveComponentFromEntity<TComponent>(Guid entityId) where TComponent : IComponent
          {
          var pool = GetComponentPool<TComponent>();
          pool.RemoveEntity(entityId);
          }
          }



          1. Program.cs


          Where it all comes together.



          class Program
          {
          static void Main(string args)
          {
          #region Composition Root

          var entityManager = new EntityManager();

          var drawingComponentTypes =
          new Type {
          typeof(VisibleComponent),
          typeof(PhysicalComponent) };

          var drawingSystem = new DrawingSystem(drawingComponentTypes);

          var visibleComponent =
          new PoolDecorator<VisibleComponent>(
          new ComponentPool<VisibleComponent>(), entityManager, drawingSystem);

          var physicalComponent =
          new PoolDecorator<PhysicalComponent>(
          new ComponentPool<PhysicalComponent>(), entityManager, drawingSystem);

          entityManager.AddSystems(drawingSystem);
          entityManager.AddComponentPool(visibleComponent);
          entityManager.AddComponentPool(physicalComponent);

          #endregion

          var entity = new Entity(entityManager.CreateEntity());

          entityManager.AddComponentToEntity(
          entity.EntityId,
          new PhysicalComponent() { X = 0, Y = 0 });

          Console.WriteLine($"Added physical component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

          entityManager.AddComponentToEntity(
          entity.EntityId,
          new VisibleComponent() { Appearance = Appearance.Monster });

          Console.WriteLine($"Added visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

          entityManager.RemoveComponentFromEntity<VisibleComponent>(entity.EntityId);

          Console.WriteLine($"Removed visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

          Console.ReadLine();
          }
          }





          and maybe it's possible to create collections that require no entityId, so they only store the reference to the component that should get updated.




          As mentioned in the referenced wiki, that's actually discouraged.




          It is a common practice to use a unique ID for each entity. This is not a requirement, but it has several advantages:




          • The entity can be referred using the ID instead of a pointer. This is more robust, as it would allow for the entity to be destroyed without leaving dangling pointers.

          • It helps for saving state externally. When the state is loaded again, there is no need for pointers to be reconstructed.

          • Data can be shuffled around in memory as needed.

          • Entity ids can be used when communicating over a network to uniquely identify the entity.







          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54231778%2fcreate-references-to-objects-and-hold-these-references-in-a-cache%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1





            +100









            The Entity-components-system asks for a specific design.




            ECS follows the composition over inheritance principle




            Dealing with pools of components, which are in essence raw data, it makes sense to handle this data with reference to the actual component type -- given you'll want to apply specific behaviors for each.



            The decorator pattern plays nicely with composition, adding behaviors by wrapping types. It also allows EntityManager to delegate responsibilities to the component pools, instead of having one massive decision tree that has to handle all cases.



            Let's implement an example.




            Suppose there is a drawing function. This would be a "System" that iterates through all entities that have both a physical and a visible component, and draws them. The visible component could typically have some information about how an entity should look (e.g. human, monster, sparks flying around, flying arrow), and use the physical component to know where to draw it.





            1. Entity.cs



            An entity will be typically made up of an ID and a list of components that are attached to it.




            class Entity
            {
            public Entity(Guid entityId)
            {
            EntityId = entityId;
            Components = new List<IComponent>();
            }

            public Guid EntityId { get; }
            public List<IComponent> Components { get; }
            }



            1. Component.cs


            Starting with the marker interface.



            interface IComponent { }

            enum Appearance : byte
            {
            Human,
            Monster,
            SparksFlyingAround,
            FlyingArrow
            }

            class VisibleComponent : IComponent
            {
            public Appearance Appearance { get; set; }
            }

            class PhysicalComponent : IComponent
            {
            public double X { get; set; }
            public double Y { get; set; }
            }



            1. System.cs


            Adding a collection for the SystemEntities.



            interface ISystem
            {
            ISet<Guid> SystemEntities { get; }
            Type ComponentTypes { get; }

            void Run();
            }

            class DrawingSystem : ISystem
            {
            public DrawingSystem(params Type componentTypes)
            {
            ComponentTypes = componentTypes;
            SystemEntities = new HashSet<Guid>();
            }

            public ISet<Guid> SystemEntities { get; }

            public Type ComponentTypes { get; }

            public void Run()
            {
            foreach (var entity in SystemEntities)
            {
            Draw(entity);
            }
            }

            private void Draw(Guid entity) { /*Do Magic*/ }
            }



            1. ComponentPool.cs


            Next, we'll lay the ground work for what's to come. Our component pools should also have a non-generic interface, that we can fall back upon when we can't supply a component type.



            interface IComponentPool
            {
            void RemoveEntity(Guid entityId);
            bool ContainsEntity(Guid entityId);
            }

            interface IComponentPool<T> : IComponentPool
            {
            void AddEntity(Guid entityId, T component);
            }

            class ComponentPool<T> : IComponentPool<T>
            {
            private Dictionary<Guid, T> component = new Dictionary<Guid, T>();

            public void AddEntity(Guid entityId, T component)
            {
            this.component.Add(entityId, component);
            }

            public void RemoveEntity(Guid entityId)
            {
            component.Remove(entityId);
            }

            public bool ContainsEntity(Guid entityId)
            {
            return component.ContainsKey(entityId);
            }
            }


            Next step is the pool decorator. The decorator pattern is implemented by exposing the same interface as the class it wraps, applying any desired behavior in the process. In our case, we want to check if added entities posses all the component types a system requires. And if they do, add them to the collection.



            class PoolDecorator<T> : IComponentPool<T>
            {
            private readonly IComponentPool<T> wrappedPool;
            private readonly EntityManager entityManager;
            private readonly ISystem system;

            public PoolDecorator(IComponentPool<T> componentPool, EntityManager entityManager, ISystem system)
            {
            this.wrappedPool = componentPool;
            this.entityManager = entityManager;
            this.system = system;
            }

            public void AddEntity(Guid entityId, T component)
            {
            wrappedPool.AddEntity(entityId, component);

            if (system.ComponentTypes
            .Select(t => entityManager.GetComponentPool(t))
            .All(p => p.ContainsEntity(entityId)))
            {
            system.SystemEntities.Add(entityId);
            }
            }

            public void RemoveEntity(Guid entityId)
            {
            wrappedPool.RemoveEntity(entityId);
            system.SystemEntities.Remove(entityId);
            }

            public bool ContainsEntity(Guid entityId)
            {
            return wrappedPool.ContainsEntity(entityId);
            }
            }


            As said, you could place the burden of checking, and managing the system collections, on EntityManager. But our current design tends to diminish complexity and provide more flexibility in the long run. Just wrap a pool once for each system it belongs to. If the system requires non default behavior, then you can create a new decorator specialized for that system -- without interfering with other systems.




            1. EntityManager.cs


            The orchestrator (aka mediator, controller,...)



            class EntityManager
            {
            List<ISystem> systems;
            Dictionary<Type, object> componentPools;

            public EntityManager()
            {
            systems = new List<ISystem>();
            componentPools = new Dictionary<Type, object>();
            ActiveEntities = new HashSet<Guid>();
            }

            public ISet<Guid> ActiveEntities { get; }

            public Guid CreateEntity()
            {
            Guid entityId;
            do entityId = Guid.NewGuid();
            while (!ActiveEntities.Add(entityId));

            return entityId;
            }

            public void DestroyEntity(Guid entityId)
            {
            componentPools.Values.Select(kp => (IComponentPool)kp).ToList().ForEach(c => c.RemoveEntity(entityId));
            systems.ForEach(c => c.SystemEntities.Remove(entityId));
            ActiveEntities.Remove(entityId);
            }

            public void AddSystems(params ISystem system)
            {
            systems.AddRange(systems);
            }

            public IComponentPool GetComponentPool(Type componentType)
            {
            return (IComponentPool)componentPools[componentType];
            }

            public IComponentPool<TComponent> GetComponentPool<TComponent>() where TComponent : IComponent
            {
            return (IComponentPool<TComponent>)componentPools[typeof(TComponent)];
            }

            public void AddComponentPool<TComponent>(IComponentPool<TComponent> componentPool) where TComponent : IComponent
            {
            componentPools.Add(typeof(TComponent), componentPool);
            }

            public void AddComponentToEntity<TComponent>(Guid entityId, TComponent component) where TComponent : IComponent
            {
            var pool = GetComponentPool<TComponent>();
            pool.AddEntity(entityId, component);
            }

            public void RemoveComponentFromEntity<TComponent>(Guid entityId) where TComponent : IComponent
            {
            var pool = GetComponentPool<TComponent>();
            pool.RemoveEntity(entityId);
            }
            }



            1. Program.cs


            Where it all comes together.



            class Program
            {
            static void Main(string args)
            {
            #region Composition Root

            var entityManager = new EntityManager();

            var drawingComponentTypes =
            new Type {
            typeof(VisibleComponent),
            typeof(PhysicalComponent) };

            var drawingSystem = new DrawingSystem(drawingComponentTypes);

            var visibleComponent =
            new PoolDecorator<VisibleComponent>(
            new ComponentPool<VisibleComponent>(), entityManager, drawingSystem);

            var physicalComponent =
            new PoolDecorator<PhysicalComponent>(
            new ComponentPool<PhysicalComponent>(), entityManager, drawingSystem);

            entityManager.AddSystems(drawingSystem);
            entityManager.AddComponentPool(visibleComponent);
            entityManager.AddComponentPool(physicalComponent);

            #endregion

            var entity = new Entity(entityManager.CreateEntity());

            entityManager.AddComponentToEntity(
            entity.EntityId,
            new PhysicalComponent() { X = 0, Y = 0 });

            Console.WriteLine($"Added physical component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

            entityManager.AddComponentToEntity(
            entity.EntityId,
            new VisibleComponent() { Appearance = Appearance.Monster });

            Console.WriteLine($"Added visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

            entityManager.RemoveComponentFromEntity<VisibleComponent>(entity.EntityId);

            Console.WriteLine($"Removed visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

            Console.ReadLine();
            }
            }





            and maybe it's possible to create collections that require no entityId, so they only store the reference to the component that should get updated.




            As mentioned in the referenced wiki, that's actually discouraged.




            It is a common practice to use a unique ID for each entity. This is not a requirement, but it has several advantages:




            • The entity can be referred using the ID instead of a pointer. This is more robust, as it would allow for the entity to be destroyed without leaving dangling pointers.

            • It helps for saving state externally. When the state is loaded again, there is no need for pointers to be reconstructed.

            • Data can be shuffled around in memory as needed.

            • Entity ids can be used when communicating over a network to uniquely identify the entity.







            share|improve this answer




























              1





              +100









              The Entity-components-system asks for a specific design.




              ECS follows the composition over inheritance principle




              Dealing with pools of components, which are in essence raw data, it makes sense to handle this data with reference to the actual component type -- given you'll want to apply specific behaviors for each.



              The decorator pattern plays nicely with composition, adding behaviors by wrapping types. It also allows EntityManager to delegate responsibilities to the component pools, instead of having one massive decision tree that has to handle all cases.



              Let's implement an example.




              Suppose there is a drawing function. This would be a "System" that iterates through all entities that have both a physical and a visible component, and draws them. The visible component could typically have some information about how an entity should look (e.g. human, monster, sparks flying around, flying arrow), and use the physical component to know where to draw it.





              1. Entity.cs



              An entity will be typically made up of an ID and a list of components that are attached to it.




              class Entity
              {
              public Entity(Guid entityId)
              {
              EntityId = entityId;
              Components = new List<IComponent>();
              }

              public Guid EntityId { get; }
              public List<IComponent> Components { get; }
              }



              1. Component.cs


              Starting with the marker interface.



              interface IComponent { }

              enum Appearance : byte
              {
              Human,
              Monster,
              SparksFlyingAround,
              FlyingArrow
              }

              class VisibleComponent : IComponent
              {
              public Appearance Appearance { get; set; }
              }

              class PhysicalComponent : IComponent
              {
              public double X { get; set; }
              public double Y { get; set; }
              }



              1. System.cs


              Adding a collection for the SystemEntities.



              interface ISystem
              {
              ISet<Guid> SystemEntities { get; }
              Type ComponentTypes { get; }

              void Run();
              }

              class DrawingSystem : ISystem
              {
              public DrawingSystem(params Type componentTypes)
              {
              ComponentTypes = componentTypes;
              SystemEntities = new HashSet<Guid>();
              }

              public ISet<Guid> SystemEntities { get; }

              public Type ComponentTypes { get; }

              public void Run()
              {
              foreach (var entity in SystemEntities)
              {
              Draw(entity);
              }
              }

              private void Draw(Guid entity) { /*Do Magic*/ }
              }



              1. ComponentPool.cs


              Next, we'll lay the ground work for what's to come. Our component pools should also have a non-generic interface, that we can fall back upon when we can't supply a component type.



              interface IComponentPool
              {
              void RemoveEntity(Guid entityId);
              bool ContainsEntity(Guid entityId);
              }

              interface IComponentPool<T> : IComponentPool
              {
              void AddEntity(Guid entityId, T component);
              }

              class ComponentPool<T> : IComponentPool<T>
              {
              private Dictionary<Guid, T> component = new Dictionary<Guid, T>();

              public void AddEntity(Guid entityId, T component)
              {
              this.component.Add(entityId, component);
              }

              public void RemoveEntity(Guid entityId)
              {
              component.Remove(entityId);
              }

              public bool ContainsEntity(Guid entityId)
              {
              return component.ContainsKey(entityId);
              }
              }


              Next step is the pool decorator. The decorator pattern is implemented by exposing the same interface as the class it wraps, applying any desired behavior in the process. In our case, we want to check if added entities posses all the component types a system requires. And if they do, add them to the collection.



              class PoolDecorator<T> : IComponentPool<T>
              {
              private readonly IComponentPool<T> wrappedPool;
              private readonly EntityManager entityManager;
              private readonly ISystem system;

              public PoolDecorator(IComponentPool<T> componentPool, EntityManager entityManager, ISystem system)
              {
              this.wrappedPool = componentPool;
              this.entityManager = entityManager;
              this.system = system;
              }

              public void AddEntity(Guid entityId, T component)
              {
              wrappedPool.AddEntity(entityId, component);

              if (system.ComponentTypes
              .Select(t => entityManager.GetComponentPool(t))
              .All(p => p.ContainsEntity(entityId)))
              {
              system.SystemEntities.Add(entityId);
              }
              }

              public void RemoveEntity(Guid entityId)
              {
              wrappedPool.RemoveEntity(entityId);
              system.SystemEntities.Remove(entityId);
              }

              public bool ContainsEntity(Guid entityId)
              {
              return wrappedPool.ContainsEntity(entityId);
              }
              }


              As said, you could place the burden of checking, and managing the system collections, on EntityManager. But our current design tends to diminish complexity and provide more flexibility in the long run. Just wrap a pool once for each system it belongs to. If the system requires non default behavior, then you can create a new decorator specialized for that system -- without interfering with other systems.




              1. EntityManager.cs


              The orchestrator (aka mediator, controller,...)



              class EntityManager
              {
              List<ISystem> systems;
              Dictionary<Type, object> componentPools;

              public EntityManager()
              {
              systems = new List<ISystem>();
              componentPools = new Dictionary<Type, object>();
              ActiveEntities = new HashSet<Guid>();
              }

              public ISet<Guid> ActiveEntities { get; }

              public Guid CreateEntity()
              {
              Guid entityId;
              do entityId = Guid.NewGuid();
              while (!ActiveEntities.Add(entityId));

              return entityId;
              }

              public void DestroyEntity(Guid entityId)
              {
              componentPools.Values.Select(kp => (IComponentPool)kp).ToList().ForEach(c => c.RemoveEntity(entityId));
              systems.ForEach(c => c.SystemEntities.Remove(entityId));
              ActiveEntities.Remove(entityId);
              }

              public void AddSystems(params ISystem system)
              {
              systems.AddRange(systems);
              }

              public IComponentPool GetComponentPool(Type componentType)
              {
              return (IComponentPool)componentPools[componentType];
              }

              public IComponentPool<TComponent> GetComponentPool<TComponent>() where TComponent : IComponent
              {
              return (IComponentPool<TComponent>)componentPools[typeof(TComponent)];
              }

              public void AddComponentPool<TComponent>(IComponentPool<TComponent> componentPool) where TComponent : IComponent
              {
              componentPools.Add(typeof(TComponent), componentPool);
              }

              public void AddComponentToEntity<TComponent>(Guid entityId, TComponent component) where TComponent : IComponent
              {
              var pool = GetComponentPool<TComponent>();
              pool.AddEntity(entityId, component);
              }

              public void RemoveComponentFromEntity<TComponent>(Guid entityId) where TComponent : IComponent
              {
              var pool = GetComponentPool<TComponent>();
              pool.RemoveEntity(entityId);
              }
              }



              1. Program.cs


              Where it all comes together.



              class Program
              {
              static void Main(string args)
              {
              #region Composition Root

              var entityManager = new EntityManager();

              var drawingComponentTypes =
              new Type {
              typeof(VisibleComponent),
              typeof(PhysicalComponent) };

              var drawingSystem = new DrawingSystem(drawingComponentTypes);

              var visibleComponent =
              new PoolDecorator<VisibleComponent>(
              new ComponentPool<VisibleComponent>(), entityManager, drawingSystem);

              var physicalComponent =
              new PoolDecorator<PhysicalComponent>(
              new ComponentPool<PhysicalComponent>(), entityManager, drawingSystem);

              entityManager.AddSystems(drawingSystem);
              entityManager.AddComponentPool(visibleComponent);
              entityManager.AddComponentPool(physicalComponent);

              #endregion

              var entity = new Entity(entityManager.CreateEntity());

              entityManager.AddComponentToEntity(
              entity.EntityId,
              new PhysicalComponent() { X = 0, Y = 0 });

              Console.WriteLine($"Added physical component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

              entityManager.AddComponentToEntity(
              entity.EntityId,
              new VisibleComponent() { Appearance = Appearance.Monster });

              Console.WriteLine($"Added visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

              entityManager.RemoveComponentFromEntity<VisibleComponent>(entity.EntityId);

              Console.WriteLine($"Removed visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

              Console.ReadLine();
              }
              }





              and maybe it's possible to create collections that require no entityId, so they only store the reference to the component that should get updated.




              As mentioned in the referenced wiki, that's actually discouraged.




              It is a common practice to use a unique ID for each entity. This is not a requirement, but it has several advantages:




              • The entity can be referred using the ID instead of a pointer. This is more robust, as it would allow for the entity to be destroyed without leaving dangling pointers.

              • It helps for saving state externally. When the state is loaded again, there is no need for pointers to be reconstructed.

              • Data can be shuffled around in memory as needed.

              • Entity ids can be used when communicating over a network to uniquely identify the entity.







              share|improve this answer


























                1





                +100







                1





                +100



                1




                +100





                The Entity-components-system asks for a specific design.




                ECS follows the composition over inheritance principle




                Dealing with pools of components, which are in essence raw data, it makes sense to handle this data with reference to the actual component type -- given you'll want to apply specific behaviors for each.



                The decorator pattern plays nicely with composition, adding behaviors by wrapping types. It also allows EntityManager to delegate responsibilities to the component pools, instead of having one massive decision tree that has to handle all cases.



                Let's implement an example.




                Suppose there is a drawing function. This would be a "System" that iterates through all entities that have both a physical and a visible component, and draws them. The visible component could typically have some information about how an entity should look (e.g. human, monster, sparks flying around, flying arrow), and use the physical component to know where to draw it.





                1. Entity.cs



                An entity will be typically made up of an ID and a list of components that are attached to it.




                class Entity
                {
                public Entity(Guid entityId)
                {
                EntityId = entityId;
                Components = new List<IComponent>();
                }

                public Guid EntityId { get; }
                public List<IComponent> Components { get; }
                }



                1. Component.cs


                Starting with the marker interface.



                interface IComponent { }

                enum Appearance : byte
                {
                Human,
                Monster,
                SparksFlyingAround,
                FlyingArrow
                }

                class VisibleComponent : IComponent
                {
                public Appearance Appearance { get; set; }
                }

                class PhysicalComponent : IComponent
                {
                public double X { get; set; }
                public double Y { get; set; }
                }



                1. System.cs


                Adding a collection for the SystemEntities.



                interface ISystem
                {
                ISet<Guid> SystemEntities { get; }
                Type ComponentTypes { get; }

                void Run();
                }

                class DrawingSystem : ISystem
                {
                public DrawingSystem(params Type componentTypes)
                {
                ComponentTypes = componentTypes;
                SystemEntities = new HashSet<Guid>();
                }

                public ISet<Guid> SystemEntities { get; }

                public Type ComponentTypes { get; }

                public void Run()
                {
                foreach (var entity in SystemEntities)
                {
                Draw(entity);
                }
                }

                private void Draw(Guid entity) { /*Do Magic*/ }
                }



                1. ComponentPool.cs


                Next, we'll lay the ground work for what's to come. Our component pools should also have a non-generic interface, that we can fall back upon when we can't supply a component type.



                interface IComponentPool
                {
                void RemoveEntity(Guid entityId);
                bool ContainsEntity(Guid entityId);
                }

                interface IComponentPool<T> : IComponentPool
                {
                void AddEntity(Guid entityId, T component);
                }

                class ComponentPool<T> : IComponentPool<T>
                {
                private Dictionary<Guid, T> component = new Dictionary<Guid, T>();

                public void AddEntity(Guid entityId, T component)
                {
                this.component.Add(entityId, component);
                }

                public void RemoveEntity(Guid entityId)
                {
                component.Remove(entityId);
                }

                public bool ContainsEntity(Guid entityId)
                {
                return component.ContainsKey(entityId);
                }
                }


                Next step is the pool decorator. The decorator pattern is implemented by exposing the same interface as the class it wraps, applying any desired behavior in the process. In our case, we want to check if added entities posses all the component types a system requires. And if they do, add them to the collection.



                class PoolDecorator<T> : IComponentPool<T>
                {
                private readonly IComponentPool<T> wrappedPool;
                private readonly EntityManager entityManager;
                private readonly ISystem system;

                public PoolDecorator(IComponentPool<T> componentPool, EntityManager entityManager, ISystem system)
                {
                this.wrappedPool = componentPool;
                this.entityManager = entityManager;
                this.system = system;
                }

                public void AddEntity(Guid entityId, T component)
                {
                wrappedPool.AddEntity(entityId, component);

                if (system.ComponentTypes
                .Select(t => entityManager.GetComponentPool(t))
                .All(p => p.ContainsEntity(entityId)))
                {
                system.SystemEntities.Add(entityId);
                }
                }

                public void RemoveEntity(Guid entityId)
                {
                wrappedPool.RemoveEntity(entityId);
                system.SystemEntities.Remove(entityId);
                }

                public bool ContainsEntity(Guid entityId)
                {
                return wrappedPool.ContainsEntity(entityId);
                }
                }


                As said, you could place the burden of checking, and managing the system collections, on EntityManager. But our current design tends to diminish complexity and provide more flexibility in the long run. Just wrap a pool once for each system it belongs to. If the system requires non default behavior, then you can create a new decorator specialized for that system -- without interfering with other systems.




                1. EntityManager.cs


                The orchestrator (aka mediator, controller,...)



                class EntityManager
                {
                List<ISystem> systems;
                Dictionary<Type, object> componentPools;

                public EntityManager()
                {
                systems = new List<ISystem>();
                componentPools = new Dictionary<Type, object>();
                ActiveEntities = new HashSet<Guid>();
                }

                public ISet<Guid> ActiveEntities { get; }

                public Guid CreateEntity()
                {
                Guid entityId;
                do entityId = Guid.NewGuid();
                while (!ActiveEntities.Add(entityId));

                return entityId;
                }

                public void DestroyEntity(Guid entityId)
                {
                componentPools.Values.Select(kp => (IComponentPool)kp).ToList().ForEach(c => c.RemoveEntity(entityId));
                systems.ForEach(c => c.SystemEntities.Remove(entityId));
                ActiveEntities.Remove(entityId);
                }

                public void AddSystems(params ISystem system)
                {
                systems.AddRange(systems);
                }

                public IComponentPool GetComponentPool(Type componentType)
                {
                return (IComponentPool)componentPools[componentType];
                }

                public IComponentPool<TComponent> GetComponentPool<TComponent>() where TComponent : IComponent
                {
                return (IComponentPool<TComponent>)componentPools[typeof(TComponent)];
                }

                public void AddComponentPool<TComponent>(IComponentPool<TComponent> componentPool) where TComponent : IComponent
                {
                componentPools.Add(typeof(TComponent), componentPool);
                }

                public void AddComponentToEntity<TComponent>(Guid entityId, TComponent component) where TComponent : IComponent
                {
                var pool = GetComponentPool<TComponent>();
                pool.AddEntity(entityId, component);
                }

                public void RemoveComponentFromEntity<TComponent>(Guid entityId) where TComponent : IComponent
                {
                var pool = GetComponentPool<TComponent>();
                pool.RemoveEntity(entityId);
                }
                }



                1. Program.cs


                Where it all comes together.



                class Program
                {
                static void Main(string args)
                {
                #region Composition Root

                var entityManager = new EntityManager();

                var drawingComponentTypes =
                new Type {
                typeof(VisibleComponent),
                typeof(PhysicalComponent) };

                var drawingSystem = new DrawingSystem(drawingComponentTypes);

                var visibleComponent =
                new PoolDecorator<VisibleComponent>(
                new ComponentPool<VisibleComponent>(), entityManager, drawingSystem);

                var physicalComponent =
                new PoolDecorator<PhysicalComponent>(
                new ComponentPool<PhysicalComponent>(), entityManager, drawingSystem);

                entityManager.AddSystems(drawingSystem);
                entityManager.AddComponentPool(visibleComponent);
                entityManager.AddComponentPool(physicalComponent);

                #endregion

                var entity = new Entity(entityManager.CreateEntity());

                entityManager.AddComponentToEntity(
                entity.EntityId,
                new PhysicalComponent() { X = 0, Y = 0 });

                Console.WriteLine($"Added physical component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

                entityManager.AddComponentToEntity(
                entity.EntityId,
                new VisibleComponent() { Appearance = Appearance.Monster });

                Console.WriteLine($"Added visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

                entityManager.RemoveComponentFromEntity<VisibleComponent>(entity.EntityId);

                Console.WriteLine($"Removed visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

                Console.ReadLine();
                }
                }





                and maybe it's possible to create collections that require no entityId, so they only store the reference to the component that should get updated.




                As mentioned in the referenced wiki, that's actually discouraged.




                It is a common practice to use a unique ID for each entity. This is not a requirement, but it has several advantages:




                • The entity can be referred using the ID instead of a pointer. This is more robust, as it would allow for the entity to be destroyed without leaving dangling pointers.

                • It helps for saving state externally. When the state is loaded again, there is no need for pointers to be reconstructed.

                • Data can be shuffled around in memory as needed.

                • Entity ids can be used when communicating over a network to uniquely identify the entity.







                share|improve this answer













                The Entity-components-system asks for a specific design.




                ECS follows the composition over inheritance principle




                Dealing with pools of components, which are in essence raw data, it makes sense to handle this data with reference to the actual component type -- given you'll want to apply specific behaviors for each.



                The decorator pattern plays nicely with composition, adding behaviors by wrapping types. It also allows EntityManager to delegate responsibilities to the component pools, instead of having one massive decision tree that has to handle all cases.



                Let's implement an example.




                Suppose there is a drawing function. This would be a "System" that iterates through all entities that have both a physical and a visible component, and draws them. The visible component could typically have some information about how an entity should look (e.g. human, monster, sparks flying around, flying arrow), and use the physical component to know where to draw it.





                1. Entity.cs



                An entity will be typically made up of an ID and a list of components that are attached to it.




                class Entity
                {
                public Entity(Guid entityId)
                {
                EntityId = entityId;
                Components = new List<IComponent>();
                }

                public Guid EntityId { get; }
                public List<IComponent> Components { get; }
                }



                1. Component.cs


                Starting with the marker interface.



                interface IComponent { }

                enum Appearance : byte
                {
                Human,
                Monster,
                SparksFlyingAround,
                FlyingArrow
                }

                class VisibleComponent : IComponent
                {
                public Appearance Appearance { get; set; }
                }

                class PhysicalComponent : IComponent
                {
                public double X { get; set; }
                public double Y { get; set; }
                }



                1. System.cs


                Adding a collection for the SystemEntities.



                interface ISystem
                {
                ISet<Guid> SystemEntities { get; }
                Type ComponentTypes { get; }

                void Run();
                }

                class DrawingSystem : ISystem
                {
                public DrawingSystem(params Type componentTypes)
                {
                ComponentTypes = componentTypes;
                SystemEntities = new HashSet<Guid>();
                }

                public ISet<Guid> SystemEntities { get; }

                public Type ComponentTypes { get; }

                public void Run()
                {
                foreach (var entity in SystemEntities)
                {
                Draw(entity);
                }
                }

                private void Draw(Guid entity) { /*Do Magic*/ }
                }



                1. ComponentPool.cs


                Next, we'll lay the ground work for what's to come. Our component pools should also have a non-generic interface, that we can fall back upon when we can't supply a component type.



                interface IComponentPool
                {
                void RemoveEntity(Guid entityId);
                bool ContainsEntity(Guid entityId);
                }

                interface IComponentPool<T> : IComponentPool
                {
                void AddEntity(Guid entityId, T component);
                }

                class ComponentPool<T> : IComponentPool<T>
                {
                private Dictionary<Guid, T> component = new Dictionary<Guid, T>();

                public void AddEntity(Guid entityId, T component)
                {
                this.component.Add(entityId, component);
                }

                public void RemoveEntity(Guid entityId)
                {
                component.Remove(entityId);
                }

                public bool ContainsEntity(Guid entityId)
                {
                return component.ContainsKey(entityId);
                }
                }


                Next step is the pool decorator. The decorator pattern is implemented by exposing the same interface as the class it wraps, applying any desired behavior in the process. In our case, we want to check if added entities posses all the component types a system requires. And if they do, add them to the collection.



                class PoolDecorator<T> : IComponentPool<T>
                {
                private readonly IComponentPool<T> wrappedPool;
                private readonly EntityManager entityManager;
                private readonly ISystem system;

                public PoolDecorator(IComponentPool<T> componentPool, EntityManager entityManager, ISystem system)
                {
                this.wrappedPool = componentPool;
                this.entityManager = entityManager;
                this.system = system;
                }

                public void AddEntity(Guid entityId, T component)
                {
                wrappedPool.AddEntity(entityId, component);

                if (system.ComponentTypes
                .Select(t => entityManager.GetComponentPool(t))
                .All(p => p.ContainsEntity(entityId)))
                {
                system.SystemEntities.Add(entityId);
                }
                }

                public void RemoveEntity(Guid entityId)
                {
                wrappedPool.RemoveEntity(entityId);
                system.SystemEntities.Remove(entityId);
                }

                public bool ContainsEntity(Guid entityId)
                {
                return wrappedPool.ContainsEntity(entityId);
                }
                }


                As said, you could place the burden of checking, and managing the system collections, on EntityManager. But our current design tends to diminish complexity and provide more flexibility in the long run. Just wrap a pool once for each system it belongs to. If the system requires non default behavior, then you can create a new decorator specialized for that system -- without interfering with other systems.




                1. EntityManager.cs


                The orchestrator (aka mediator, controller,...)



                class EntityManager
                {
                List<ISystem> systems;
                Dictionary<Type, object> componentPools;

                public EntityManager()
                {
                systems = new List<ISystem>();
                componentPools = new Dictionary<Type, object>();
                ActiveEntities = new HashSet<Guid>();
                }

                public ISet<Guid> ActiveEntities { get; }

                public Guid CreateEntity()
                {
                Guid entityId;
                do entityId = Guid.NewGuid();
                while (!ActiveEntities.Add(entityId));

                return entityId;
                }

                public void DestroyEntity(Guid entityId)
                {
                componentPools.Values.Select(kp => (IComponentPool)kp).ToList().ForEach(c => c.RemoveEntity(entityId));
                systems.ForEach(c => c.SystemEntities.Remove(entityId));
                ActiveEntities.Remove(entityId);
                }

                public void AddSystems(params ISystem system)
                {
                systems.AddRange(systems);
                }

                public IComponentPool GetComponentPool(Type componentType)
                {
                return (IComponentPool)componentPools[componentType];
                }

                public IComponentPool<TComponent> GetComponentPool<TComponent>() where TComponent : IComponent
                {
                return (IComponentPool<TComponent>)componentPools[typeof(TComponent)];
                }

                public void AddComponentPool<TComponent>(IComponentPool<TComponent> componentPool) where TComponent : IComponent
                {
                componentPools.Add(typeof(TComponent), componentPool);
                }

                public void AddComponentToEntity<TComponent>(Guid entityId, TComponent component) where TComponent : IComponent
                {
                var pool = GetComponentPool<TComponent>();
                pool.AddEntity(entityId, component);
                }

                public void RemoveComponentFromEntity<TComponent>(Guid entityId) where TComponent : IComponent
                {
                var pool = GetComponentPool<TComponent>();
                pool.RemoveEntity(entityId);
                }
                }



                1. Program.cs


                Where it all comes together.



                class Program
                {
                static void Main(string args)
                {
                #region Composition Root

                var entityManager = new EntityManager();

                var drawingComponentTypes =
                new Type {
                typeof(VisibleComponent),
                typeof(PhysicalComponent) };

                var drawingSystem = new DrawingSystem(drawingComponentTypes);

                var visibleComponent =
                new PoolDecorator<VisibleComponent>(
                new ComponentPool<VisibleComponent>(), entityManager, drawingSystem);

                var physicalComponent =
                new PoolDecorator<PhysicalComponent>(
                new ComponentPool<PhysicalComponent>(), entityManager, drawingSystem);

                entityManager.AddSystems(drawingSystem);
                entityManager.AddComponentPool(visibleComponent);
                entityManager.AddComponentPool(physicalComponent);

                #endregion

                var entity = new Entity(entityManager.CreateEntity());

                entityManager.AddComponentToEntity(
                entity.EntityId,
                new PhysicalComponent() { X = 0, Y = 0 });

                Console.WriteLine($"Added physical component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

                entityManager.AddComponentToEntity(
                entity.EntityId,
                new VisibleComponent() { Appearance = Appearance.Monster });

                Console.WriteLine($"Added visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

                entityManager.RemoveComponentFromEntity<VisibleComponent>(entity.EntityId);

                Console.WriteLine($"Removed visible component, number of drawn entities: {drawingSystem.SystemEntities.Count}.");

                Console.ReadLine();
                }
                }





                and maybe it's possible to create collections that require no entityId, so they only store the reference to the component that should get updated.




                As mentioned in the referenced wiki, that's actually discouraged.




                It is a common practice to use a unique ID for each entity. This is not a requirement, but it has several advantages:




                • The entity can be referred using the ID instead of a pointer. This is more robust, as it would allow for the entity to be destroyed without leaving dangling pointers.

                • It helps for saving state externally. When the state is loaded again, there is no need for pointers to be reconstructed.

                • Data can be shuffled around in memory as needed.

                • Entity ids can be used when communicating over a network to uniquely identify the entity.








                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 20 at 0:00









                FunkFunk

                5,4191826




                5,4191826






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54231778%2fcreate-references-to-objects-and-hold-these-references-in-a-cache%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Liquibase includeAll doesn't find base path

                    How to use setInterval in EJS file?

                    Petrus Granier-Deferre