PrevUpHomeNext

Appendix

Appendix A. Entity-component-systems
Appendix B. Visual Studio watch visualizers

An entity-component-system (ECS) allows users to create entities which consist of components. A simplified way of thinking about that is a container of instances of unique types. Another way of thinking about said entities is like they are objects produced from multiple inheritance only they are constructed in runtime, as opposed to compile-time.

Here's a piece of code that might be used in a simple hypothetical ECS:

entity e;
e.add_component(new xml_serializer);
e.add_component(new book_data);
// now the entity contains data and a way to serialize this data
// ...
// here we can test if an entity has the components we need
if(e.has_component<xml_serializer>())
{
    e.get_component<xml_serializer>()->serialize();
}

See how we can think of e as a container of various objects, or as a class derived from both serializer and data. However it is not exactly a container as it cannot have two instances of the same class, and it is not exactly a class with multiple inheritance as its contents cannot be statically analyzed.

They allow the users to achieve true decoupling of their subsystems. For example if we extend the above example to have a registered component of type serializer, which is a pure virtual class with a method virtual void serialize() = 0, the code example from above would still work, but we would be able to change the last part to something a bit more useful:

if(e.has_component<serializer>())
{
    e.get_component<serializer>()->serialize();
}

Now all functions that want to call serialize for an object may as well be oblivious to what the actual serializer within the entity. Keep in mind that this is nearly impossible to achieve with plain multiple inheritance as users would have to handle the combinatorial explosion of different serializer's, data's and other possible super-classes.

The above example shows that an ECS is, in most cases, a better choice than multiple inheritance. But what about composition?

Well, an ECS is a type of composition, with one difference. An entity has no idea what kind of components may be a part of it.

Imagine a the straight-forward way to composition. An object from our system will have methods like get_serializer(), get_data(), and more. This means that every time we add a new sub-system, we'll have to change the object type to "enrich" it with its new components. Removing the aforementioned limitation allows independent sub-system development – without changing the code of the original product. I also allows the introduction of entire subsystems with dynamic libraries, which don't change the binary. For example, writing an entirely new serialization mechanism – say encrypted serialization – for a product and introducing it as an optional plug-in becomes a breeze.

There exists a technique, often also called entity-component-system, that is not polymorphic. It can be combined to a degree with code like the one described above but it requires special maintenance.

Essentially what it does is, the entity has pointers (or sometime indexes) of concrete components, that aren't managed by it, but by the subsystems that use these components. The subsystems contain dense arrays of these components, which they process, often being oblivious of entities and other higher-level concepts.

This is done in very performance heavy pieces of software, where even the cache locality of the data is critical. Since polymorphism is incompatible with cache locality, those systems sacrifice (at least to some degree) the ease of use and maintainability for the speed.

This is especially popular in high-end games, where in order to produce state of the art graphics and physics with a decent framerate, each microsecond is of importance.

They are very popular in game development, as most objects in a game have many different aspects for different sub-systems. Still, being as powerful as they are, they find their place in many other pieces of software developed in C++, Java or C#.

It is the author's opinion that any big project with complex objects could benefit from using an ECS. Indeed games and game engines are a prime example of such a project, but there are many others. Any software that has optional dynamic library plug-ins, most CAD systems, graph editors, project management tools, and many others.

Most script-language objects natively support a functionality resembling the polymorphic form of these systems, and most of them call it Mixins.

  • In his e-book Game Programming Patterns, Robert Nystrom has a wonderful chapter, called Components, in which he describes the benefits of using an ECS and gives a simple example.
  • Adam Martin has a great series of articles on the subject. Especially on how such systems are related to game and MMOG development.
  • An existing simple classic entity-component-system is cistron by Karel Crombecq. You can also check out the slides from his presentation on the subject.
  • Building Object Systems is a talk by Alex Duran. The slides are available here.
  • Chris Granger has an article on the benefits of using an entity-component-system in ClojureScript for game development
  • An interesting discussion on the subject can be found at the xkcd forums.

If you're using Microsoft Visual Studio, you can install special watch visualizers which will make adding boost::mixin::object in a watch window a better experience.

There are two ways to do this, which will work on both the full and express versions of Visual Studio.

The result when adding a watch on an object should resemble this:

vs_natvis

To install this visualizer:

  • Locate boost_mixin.natvis in your Boost.Mixin installation. It should be in the tools subdirectory.
  • To install for your user only, copy it to <Documents>\<Visual Studio Version>\Visualizers. If the directory doesn't exist, create it manually.
  • To install for all users, copy it to %VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers. You will need administrator access to do this.

The result when adding a watch on an object should resemble this:

vs_autoexp

To install this visualizer:

  • Locate autoexp.txt in your Boost.Mixin installation. It should be in the tools subdirectory.
  • Open it in a text editor
  • Open %VSINSTALLDIR%\Common7\Packages\Debugger\autoexp.dat in a text editor
  • Typically it will end with a [hresult] section.
  • Paste the entire content of autoexp.txt just before the line [hresult]

To use this visualizer with Visual Studio versions 2012 or newer, you should also go to in your menus to Tools > Options > Debugging > Edit and Continue and there check Enable native Edit and Continue. Warning: This will also disable any natvis visualizers you might have installed.

No matter which (if any) of these visualizers you use, to watch concrete mixin from an object, you should add a new watch where you explicitly cast the address to the correct mixin type. The visualizers only help you quickly find the address and the target type. They don't (and unfortunately can't) perform the cast.

If you perform the cast correctly, the result will resemble this:

vs_watch


PrevUpHomeNext