10
\$\begingroup\$

I recently asked about how to separate entities from their behaviour and the main answer linked to this article: http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

The ultimate concept written about here is that of: OBJECT AS A PURE AGGREGATION.

I'm wondering how I might go about creating game entities as pure aggregation using C#. I've not quite grasped the concept of how this might work yet. (Perhaps the entity is an array of objects implementing a certain interface or base type?)

My current thinking still involves having a concrete class for each entity type that then implements the relevant interfaces (IMoveable, ICollectable, ISpeakable etc).

How can I go about creating an entity purely as an aggregation without having any concrete type for that entity?

\$\endgroup\$
1
  • \$\begingroup\$ If you're still interested I can send you my small entity system in C#. It's not amazing, but it works. \$\endgroup\$ Commented Jun 22, 2011 at 20:30

3 Answers 3

6
\$\begingroup\$

The "pure aggregation" approach described by West in that linked article eschews an "entity" object altogether. There are components, floating around in memory, but they are tied together only by implicit relationships, if at all.

One way to do this is a so-called outboard approach. In such a system, components are held by systems that manage or otherwise control them (I use the term "manage" here, but you shouldn't take this to mean I'm suggesting that you have a bunch of *Manager classes to hold component types). For example, your physics system may hold on to a bunch of things representing each rigid body in its simulation world, and may expose those things as PhysicsComponents. The components can be the actual objects handled by the subsystem in question, or they can be proxies for those objects, as needed.

In such a system there isn't necessarily a need for an "Entity" class to hold a collection of references to the components that comprise it; instead a notification is raised concerning the creation or destruction of an "entity" and each subsystem that handles components looks at the description of the created/destroyed entity (which is typically loaded from some data) and determines if a component is necessary for it.

One of the advantages to this approach is that you get really good locality of reference for each component. Unfortunately it's a bit weird, overall, and not the most friendly flavor of component-based entities I've encountered. Sometimes it is really convenient to have a real object that represents an entity, even if that object does little more then aggregate weak references to components that are still held by other subsystems (if nothing else it provides a easy way to route messages between components).

There are several good ways to implement component oriented game object systems; it really, really, really helps if you have a solid idea of the requirements you want out of your system -- you can look at what popular frameworks like Unity do for examples. Without setting strict requirements for yourself, you may run into the problem of endlessly "designing" the system without ever really building it, trying in vain to hit upon the perfect implementation. For whatever reason I've seen this a lot with component systems.

\$\endgroup\$
3
\$\begingroup\$

The way Unity does it is that all scripts (in your case, game code that's specific to a type of game object) derive from a base class, MonoBehaviour, which itself derives from the more relevant-to-your-case Component class. You never edit (and don't have access to the code of) the GameObject class.

The game object is in charge of containing all those Components. It's also ostensibly in charge of calling the relevant functions on them (i.e. Update). Unity uses reflection to determine what functions to call (look at the "Overridable Functions" section on this page), but you'd probably want to make them virtual.

So one of the mechanisms that you use in Unity is getting components on your current game object (or its children) by type. There are some helper properties that wrap some of the common stuff. For example, if you want to access the game object's Transform component (to control the game object's position/rotation/scale), you would normally have to do something like this.GetComponent<Transform>().position, but they wrap that into a helper this.transform.position call. Another common pattern is accessing the current game object's Renderer component. So if you want to do something like change the current game object's material, from another script you might do something like this.renderer.material = someOtherMaterial, and your game object updates appropriately.

One of the ways this works in Unity is that their editor is set up such that you can create game objects in your scene that have components already hooked up. In Unity's case, all game objects have a Transform component, but it can also contain built-in types like AudioListener or Renderer, which do what you would expect. Or you can add your own components that do whatever it is you want them to do. The editor also exposes public/serializable fields on your components so you don't have to make different scripts if you want to use the same basic code but change a few magic numbers around.

All in all it's pretty slick, and I'd suggest downloading the free version of Unity and playing around with how their scripting system is set up as a pretty decent proof of concept of what you want to achieve.

\$\endgroup\$
0
\$\begingroup\$

I like a approach more close to Adam's vision from the t-machine blog. Components should be only data, and systems do all the job with them.

See an example of ES implementation in C#: https://github.com/thelinuxlich/artemis_CSharp

And an example game using it(XNA 4): https://github.com/thelinuxlich/starwarrior_CSharp

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .