Using C# and XNA 4, I've made the decision to go for an entity-component based design for my game after reading such posts as this and this, but I'm now struggling to find how to retrieve components once they've been added to an entity.
Some articles I've read say that when a component is created, register it with the system that will act upon it, using a messaging system. A drawback I see here is that if a system needs 2 components to act (say CollideComponent and PositionComponent) then this gets complicated (and I can't figure how it would work).
The other possibility, and the one that I'm currently pursuing, is to have a system ask whether an entity has a particular component when it needs it. However I've not seen any code examples, only theory on the net, so I've been trying to muddle it together. Some code here might explain how far I've got :
First a System
:
public class RenderingSystem : IGameSystem
{
public void PerformAction(IQueryable<IGameObject> gameObjects)
{
foreach (var gameObject in gameObjects)
{
RenderableGameComponent renderableGameComponent = gameObject.GetComponent<RenderableGameComponent>(ComponentType.Renderable);
if (renderableGameComponent != null)
{
this.spriteBatch.Draw(renderableGameComponent.Texture, renderableGameComponent.DrawablePosition, Color.White);
}
}
}
}
Now the actual GameObject
:
public class GameObject : IGameObject
{
private List<IGameComponent> gameComponents;
private ComponentType componentTypes;
public void AddComponent(IGameComponent component)
{
this.gameComponents.Add(component);
this.componentTypes = this.componentTypes | component.ComponentType;
}
public T GetComponent<T>(ComponentType componentType)
{
return (T)this.gameComponents.FirstOrDefault(gc => gc.ComponentType == componentType);
}
}
And finally the Component
and ComponentType
enumeration :
public class RenderableGameComponent : IGameComponent
{
public Texture2D Texture { get; set; }
public Vector2 DrawablePosition { get; set; }
public ComponentType ComponentType
{
get { return ComponentType.Renderable; }
}
}
[Flags]
public enum ComponentType
{
Renderable = 1,
Updateable = 2,
Position = 4,
}
Now as you might be able to see, I'm trying to use bitwise operations on the ComponentType
enumeration that every Component
of each GameObject
has. The reason being I thought this would be a much cleaner approach when trying to get the required Component
out of the GameObject
when asked by a System
(also refer to link 1 above).
I'm trying to get away from passing in a type, and doing an iteration over all the Component
s of a GameObject
. eg:
foreach (var component in this.GameComponents)
{
if (component.GetType() == requestedType) { return component; }
}
This is because when there are a few hundred bullets on the screen and a CollidableSystem
is created, it will massively slow the game down checking every type. I've had experience with this when creating a previous game, but admittedly, that was using an inheritance based design system.
It worries me that for each System
that is created, it will have to iterate over every GameObject
every tick asking the same question every time, "Do you have the component I am looking for ?" and still doing a lot of casting and null checks.
Now my question is this. I want to know whether there is a de facto design pattern for getting Component
s from GameObject
s that don't require null checks or casting ? Someway a System
will say "Give me this component, I know that you have it" and not bother wasting time asking those GameObject
s that don't have the Component
. Tell, don't ask.