C# Artemis Entity System Tutorial

Artemis is a high performance Entity System framework for games, originally written in Java by Arni Arent and Tiago Costa, now ported to C#.
Its goal is to provide a clean API to abstract your game world organization into entities, components and systems.
Artemis has no dependencies (for PC, in Xbox and Windows Phone 7 we have one) and can be used with any game framework or library, 2D or 3D, and even multiplatform, if you use it with Mono/MonoTouch/Mono4Android.

Differences from the original version

We support all the features included in the original Java version, but we’ve also added the following features:

  • Multithreading Support (two ways of doing this)
  • Specialized System templates for your multithreading needs
  • Communication between Systems using a Blackboard approach
  • Bugs fixed, performance improvements
  • Xbox/WP7/Mono(Android/Linux/Mac/iOS) support
  • Events for intercepting adding/removal of entities/components
  • Blackboard for sharing common objects between systems
  • Entity Pool (to make objects reusable, minimize garbage collection activity, improve performance)
  • Small goodies, like feeding the EntityWorld with whole Entities(maybe loading from external resources), enabling/disabling systems and entities, getting Entity tag, API shortcuts(see unit tests for more on this), etc.

Getting Started

  • Entities are only an aggregation of Components, identified by a unique id
  • Components are only data
  • Systems publish/subscribe to Components, creating behavior

There is much more to tell about this paradigm and we already have rich articles which inspired this framework. Some of them:

And many more can be found here.

Your components must inherit from the class Component or ComponentPoolable if you want it to use the Artemis Component Pool. Example:

//Add this Attribute and extend ComponentPoolable if you want your Component to use Artemis Component Pool
[Artemis.Attributes.ArtemisComponentPool(InitialSize=5,Resizes=true, ResizeSize=20, isSupportMultiThread=false)]
class Velocity : ComponentPoolable
        private float velocity;
        private float angle;

        public Velocity() { }

        public Velocity(float vector)
            velocity = vector;

        public Velocity(float velocity, float angle)
            this.velocity = velocity;
            this.angle = angle;

        public float Speed {
            get { return velocity;}
            set { velocity = value; }

        public float Angle
            get { return angle; }
            set { angle = value;}

        public void AddAngle(float a)
            angle = (angle + a) % 360;

        public float AngleAsRadians
            get { return (float)Math.PI * angle / 180.0f; }

        //obligatory for poolable Components
        public void Cleanup()
             coords = Vector3.Zero;

A sample for entity assembling:

Entity e = world.CreateEntity(); // you can pass an unique ID as first parameter.
e.AddComponent(new Transform(200,400));
e.AddComponentFromPool(new Velocity(2.4f,0.9f)); // use AddComponentFromPool if the Component extend from ComponentPoolable
e.Refresh();// always call Refresh() when adding/removing components!

Your systems should inherit from one of the following templates:

  • EntitySystem – the simplest system template, not tied to components, good for stuff like collision
  • EntityProcessingSystem – a template for processing many entities, tied to components
  • IntervalEntitySystem – a simple system template, not tied to components, process periodically, based on world delta.
  • IntervalEntityProcessingSystem – a template that process entities periodically, based on world delta, tied to components.
  • ParallelEntityProcessingSystem – a template to leverage your multicore CPU for processing many entities, tied to components
  • ProcessingSystem – a template that process whichever logic you desire, without being tied to components
  • QueueProcessingSystem – instead of filter by components, this system process entities that are added to its public queue
  • HybridQueueProcessingSystem – process entities by queue and components
  • QueueProcessingSystemThreadSafe – process entities by a public static thread safe queue
  • FQueueSystemProcessingThreadSafe – process anything (not only entities) added to its public static thread safe queue
  • TagSystem – a simple system template, not tied to components, process a tagged entity
  • IntervalTagSystem – a simple system template, not tied to components, process a tagged entity periodically, based on world delta.
  • DelayedEntitySystem – a simple system template that starts process after a given time, based on world delta.
  • DelayedEntityProcessingSystem – a template that starts processing entities after a given time, based on world delta. Tied to components

And here is a system example, using Velocity and Transform components to create the Movement behavior:

//Add this attribute so the EntityWorld knows the systems it should execute, use the Layer to determine execution order
[Artemis.Attributes.ArtemisEntitySystem(ExecutionType = ExecutionType.UpdateSynchronous, Layer = 1)]
public class MovementSystem : EntityProcessingSystem {

    public MovementSystem() : base(Aspect.All(typeof(Transform), typeof(Velocity))) { }

    public override void Initialize() {}

    public override void Process(Entity e) {
        Velocity velocity = e.getComponent();
        float v = velocity.Speed;

        Transform transform = e.getComponent();

        float r = velocity.AngleAsRadians;

        float xn = transform.X + (TrigLUT.Cos(r) * v * world.Delta);
        float yn = transform.Y + (TrigLUT.Sin(r) * v * world.Delta);

        transform.SetLocation(xn, yn);

On your game initialization, create a new EntityWorld and initialize it:

var world = new EntityWorld();
world.InitializeAll(true); // pass true/false to enable/disable DataAttributes on Systems

Update or Draw the World:

world.Draw(); // do this on a different loop, e.g: every 15 ms

And you are good to go. The Entity object has some intuitive methods like Delete(), GetComponent(), RemoveComponent(), which you can see in action on the example game.


Aspects are used in the constructor of your entity systems to tell them which components they should be interested. At the moment we have three methods to build Aspects:

  • Aspect.All(params Type[] types) – Most of the time you will use this option, so the system processes entities which have all components of the Aspect.
  • Aspect.One(params Type[] types) – The system will process entities which have at least one of the components of the Aspect.
  • Aspect.Exclude(params Type[] types) – The system will not process entities which have at least one of the components of the Aspect.

You can also compose your Aspect utilizing these methods together, example:

public LogEnemySystem() : base(Aspect.All(typeof(Health)).One(typeof(Koopa),typeof(Goomba),typeof(Magikoopa)).exclude(typeof(Ghost))) {}

Extending Systems

It’s quite simple to extend the EntitySystem with your own logic, an example can be found here, which gives us less setup on systems which only uses Aspect.All(), example:

[Artemis.Attributes.ArtemisEntitySystem(ExecutionType = ExecutionType.UpdateSynchronous, Layer = 1)]
public class MovementSystem : EntityComponentProcessingSystem {
    public override void Process(Entity e,Transform transform, Velocity velocity) {
        float v = velocity.Speed;
        float r = velocity.AngleAsRadians;

        float xn = transform.X + (TrigLUT.Cos(r) * v * world.Delta);
        float yn = transform.Y + (TrigLUT.Sin(r) * v * world.Delta);

        transform.SetLocation(xn, yn);


Create your entity templates to avoid manually creating and configuring entities:

public EnemyTemplate : Artemis.IEntityTemplate {
	public Entity BuildEntity(Entity e,EntityWorld entityWorld, params object[] args) {
		e.AddComponent(new Transform(200,400));
		e.AddComponent(new Velocity(2.4f,0.9f));

Create your entities with the template applied:

var enemy = world.CreateEntityFromTemplate("BulletExplosion",array_of_parameters); // you can also use an alternative signature passing a custom unique id as the first parameter.


You can easily share common objects between systems using the blackboard, here is a XNA example, on the game initialization:

EntitySystem.BlackBoard.SetEntry("ContentManager", Content);
EntitySystem.BlackBoard.SetEntry("GraphicsDevice", GraphicsDevice);
EntitySystem.BlackBoard.SetEntry("SpriteBatch", spriteBatch);

Then you can retrieve the objects inside systems like this:

this.device = EntitySystem.BlackBoard.GetEntry("GraphicsDevice");
this.spriteBatch = EntitySystem.BlackBoard.GetEntry("SpriteBatch");
this.contentManager = EntitySystem.BlackBoard.GetEntry("ContentManager");

Games created with Artemis C#

Magnetic by Nature – by Tripleslash Studios. They also have a Kickstarter running for the game, support it!

Discussion, issues, suggestions

We have a forum section here.

 Use It !!!


  1. #1 by de www schufafrei kredit online on 10 de dezembro de 2016 - 6:38 am

    NAFG – Loved the *grow me some nip* photo when I saw it the other day – but I couldn’t think of a post around it! The other two must be newer – I went through over 50 past pages and and a whole bunch of times

  2. #2 by http://kreditvergleichejetzo.info/schnellkredit-wenig-zins-niedrig.html on 10 de dezembro de 2016 - 6:44 am

    All your tips are good, but number 3 (Get Ready to Sell) is a standout. I’ve seen hardworking people with great ideas and a sound business plan fall flat on their faces because they were afraid of selling.

  3. #3 by cheap moncler jackets on 10 de dezembro de 2016 - 6:45 am

    Bought the being a gifts for the the mother as well as she loved this. nice high quality great cost additionally my personal mom loved that. Even sent ultra quickly. When you need a gifts quickly while like this than this is someone you really need to pick!

  4. #4 by http://www.hutchingsfuneralchapel.com/MonclerSale.asp on 10 de dezembro de 2016 - 6:46 am

    Bought this particular as being a gifts of my mother and also she adored they. awesome top quality sweet expense then my mom liked that. Furthermore sent extremely accelerated. When you need a gift quick while such as this then this is actually the an it is important to choose!

  5. #5 by Johnnie on 10 de dezembro de 2016 - 6:51 am

    Which team do you support? buy imuran 50 mg tablets usps “But as he gets more and more mixed up in the fallen nature of Gotham, he can’t help but cut deals with the devil and please the powers that be, in order to get things done.”

  6. #6 by kredit selbstständig on 10 de dezembro de 2016 - 7:59 am

    Absolutely first rate and copper-bottomed, gentlemen!

  7. #8 by kredit in der probezeit on 10 de dezembro de 2016 - 8:39 am

    Jimmy díky za reakci, pÅ™imÄ›l jsi mÄ› k doplnÄ›ní. PÅ™i psaní postu jsem to nezmínil. Může nastat taková situace, že partner je zahrnut ve dvou, ale klidnÄ› i ve více sítích. PropagujeÅ¡ pÅ™es síť A a může se stát, že tam je odkaz na síť B, C, a ty ho neznáš … každý má své id. Jestli chceÅ¡, můžeÅ¡ mi poslat link z newsletru na mail: kouknu na to.

  8. #9 by Jacques on 10 de dezembro de 2016 - 8:44 am

    I’ll call back later enalapril (vasotec) classification (Reporting by Nathan Layne in New Orleans; Editing by Ken Willsand Lisa Shumaker)

1 528 529 530
(não será publicado)