Tuesday, July 13, 2010

Game Logic XIII: Components imply entities

At first, using a component based architecture feels awkward. I remember having issues when I started doing it many years ago. I wanted to communicate between components, but that was bad practice caught from doing so many years of Object Oriented development.

As my understanding of component based development grew, my opportunity to do it lessened, which was unfortunate as I feel that because of that, my appreciation never fully matured until last year when I started totally rethinking every technique I had used from the perspective of Data Oriented development.

I'd been stumbling along the ideas and benefits of Data Oriented without knowing they were related to each other while working on many different areas of engine development, and looking back I can see a few points that I could have made the leap, but didn't. But even then, after figuring it all out, I wouldn't have been able to make this latest leap.

From the beginning of this series of posts on data oriented development, I've been opting for a component-implies-entity approach to development, which is maintained by the components having primary-key like values to identify which entity they belong. Moving away from this would seem pointless, however there is a good reason to make one more step away from object orientation.

If components imply entities, does that make entities the cosmic base class of data oriented development? I think it does, and removing this crutch helps out in some odd ways.

Firstly, if you don't need an entity to identify your component, it becomes an entity in it's own right and can offer more flexibility in how it's used. Consider the humble path find. If your path finding nodes, the resultant chain of nodes that is, is allowed to exist outside of the initiator of the path request, then not only can the chain be used by the requester in the normal manner, but also used as a virtual signpost for groups of entities. Consider a path find that leaves the path find nodes hanging in space, waiting for other entities to pass by and tell them where to go if they happen to want to go in the same direction. Surely this would be quite a CPU saving if there was a common goal (which there often is).

Secondly, not using the entity as a basis gives you a better opportunity for runtime template objects. If an object is not tied to an entity, it can be used by multiple entities. Consider the component Weapon, with a instance for Handgun that has all the targeting techniques and rendering info attached, but that handgun can be used by many many entities. Using binding objects (which are your many-to-many tables of database science), lets you connect any amount of template objects to each other without actually making them coupled. Now your entities are instanced through couplings, but your code isn't coupled.

To this end, I'm giving up on calling the components of an entity in my new book components. I'm going to be calling them Elements, as any entity component should be a table row that binds an Element through existence, implying a component. The actual component might be a template object that has more information and doesn't need to be bound to the entity. Also, a component might not even belong to an entity, or might belong to multiple entities, or might be multiply owned by just one entity (consider the healing potion you have ten of in your inventory).

So there you have it. Component based architectures are great, but you can take another step and have element based architectures with bindings where necessary.

I believe that the dungeon siege component system had a form of this (through some default state template objects) but was still stuck to it's entities. I can't find the original documents that I read that stuff in so can't be sure, but I do remember it being very important thinky stuff at the time.