Skip to content

Tutorials Component System

Takumii edited this page Feb 21, 2014 · 3 revisions

HomeTutorialsComponent ▸ System

System

What is a system

Systems are the brain of components.

A world contains game objects and game objects contains components but without systems all of this will be static, nothing will happen. Systems are responsible to update components behaviors and by updating them they will interact and make the world dynamic and alive.

How to implement a system

A system must inherit the System abstract class. This class provides common interface for all systems.

public sealed class HealthSystem : System
{
	// Abstract method must be implemented
	public override void Update(GameTime gameTime) { }
	
	// Abstract method must be implemented
	public override void Register(Component component) { }

	// Abstract method must be implemented
	public override void Unregister(Component component) { }

	// Abstract property must be implemented
	public override Type[] ComponentTypes { get; set; }
}

When you inherit System, there is four abstract methods that you need to override :

  • Update
  • Register
  • Unregister
  • ComponentTypes

How to associate a system with specific components

A system can be linked to one or multiples components. This means that every time a component with a specific type is added or removed from a world, all systems associated to this component type will be notified of the change.

You have to override the ComponentTypes property to indicate which component the system will work with :

public sealed class HealthSystem : System
{
	// This system is associated to the HealthComponent
	private readonly Type[] _componentTypes = new Type[]{ typeof(HealthComponent) };

	public override Type[] ComponentTypes
	{
		get { return _componentTypes; }
	}
}

In this example, every time a HealthComponent is added or removed to the world, the information will be dispatched to the HealthSystem instance. To receive those notifications, your system must be added to a world instance.

How to associate a system with all components

If your system needs to listen for all components, you can use the ListenAllComponents property :

public sealed class MainSystem : System
{
	// No components associated to this system, it will listen for all
	private readonly Type[] _componentTypes = new Type[]{};

	public override Type[] ComponentTypes
	{
		get { return _componentTypes; }
	}
}

And here is an example of how to use the ListenAllComponents property :

MainSystem main = new MainSystem() { ListenAllComponents = true };

If you want to listen for all components, you can return an empty array for the ComponentTypes property. Even if your array isn't empty, the world will not used it because you want to listen for all components.

How system are managed

Each world has SystemManager property. This property contains an instance of SystemManager class. This class is used to manages all systems in a world.

Within a SystemManager you can only have one instance of a specific system type at time.

How to add a system

You can add a system to a world via the Add method of the SystemManager :

HealthSystem healthSystem = new HealthSystem();
myWorld.SystemManager.Add(healthSystem);

Your system can only be added to one world at time and world can only have one instance of a specific system type at time.

Once added, your system will receive all notifications (add/remove) about components that are associated to this system.

How to remove a system

To remove a system you must call the Remove method :

myWorld.SystemManager.Remove(healthSystem);

// or

myWorld.SystemManager.Remove<HealthSystem>();

// or

myWorld.SystemManager.Remove(typeof(HealthSystem));

How to retrieve a system

You can easily retrieve a specific system by its type since a world can only have one instance for a specific type :

HealthSystem healthSystem = myWorld.SystemManager.GetSystem<HealthSystem>();

// or

HealthSystem healthSystem = myWorld.SystemManager.GetSystem(typeof(HealthSystem)) as HealthSystem;

How a system is notified when a component is added to the world

Once a system has been added to a world, it will be notified when an associated component is added.

The notification is done via the Register method of the system :

// This system is associated to one component only : HealthComponent
public sealed class HealthSystem : System
{
	private List<HealthComponent> _healths = new List<HealthComponent>();
	
	// Basic implementation of the Register method
	public override void Register(Component component)
	{
		// Cast with no check for null value since a system will only receive components with a specific type
		// In this case, the HealthSystem will only get HealthComponent
		// If your system is associated to more than one component type, you must probably check the exact type
		// carefully
		HealthComponent health = component as HealthComponent;
		_healths.Add(health);	
	}
}

Now that the Register method is implemented, the system will be notified each time a HealthComponent is added.

How a system is notified when a component is removed from a world

Once a system has been added to a world, it will be notified when an associated component is removed.

The notification is done via the Unregister method of the system :

// This system is associated to one component only : HealthComponent
public sealed class HealthSystem : System
{
	private List<HealthComponent> _healths = new List<HealthComponent>();
	
	// Basic implementation of the Unregister method
	public override bool Unregister(Component component)
	{
		// Cast with no check for null value since a system will only receive components with a specific type
		// In this case, the HealthSystem will only get HealthComponent
		// If your system is associated to more than one component type, you must probably check the exact type
		// carefully
		HealthComponent health = component as HealthComponent;

		return _healths.Remove(health);	
	}
}

How a system is updated

To make systems alive, they must be updated.

The Update method of the System class will contains the system logic :

public sealed class HealthSystem : System
{
	public override void Update(GameTime gameTime)
	{
		// Add logic here
	}
}

The Update method of all systems in a world will be called when the Update method of the world instance is called :

// LoadContent of the Game class
protected override void LoadContent()
{
	_myWorld = new World();
	_myWorld.SystemManager.Add(new HealthSystem());
}

// Update of the Game class
protected override void Update(GameTime gameTime)
{
	_myWorld.Update(gameTime); // Will call Update for all systems
}