13
\$\begingroup\$

I admit, I have made the sin of overusing, and even abusing inheritance. The first (text) game project that I made when I was taking my OOP course went as far as "Locked door" and "unlocked door" from "Door" and "Room with one door", "Room with two doors", and so on from "Room".

With the (graphical) game I worked on recently, I thought I had learned my lesson and put a limit on using inheritance. However I noticed the problems soon beginning to appear. My root class was beginning to bloat more and more, and my leaf classes were full of duplicate codes.

I thought I was still doing things wrong, and after looking it up online I discovered that I wasn't the only one with this problem. It's how I ended up discovering Entity systems after some thorough research (read: googlefu)

When I began reading on it, I was able to see how clearly it was able to solve the problems I was having with the traditional OOP hierarchy with components. These were in the first readings however. When I stumbled upon more… “radical” ES approaches, such as the one at T-machine.

I began disagreeing with the methods they were using. A pure component system seemed either overkill, or rather, unintuitive, which is probably the strength of OOP. The author goes so far as to say that ES system is the opposite of OOP, and while it may be usable along OOP, it really shouldn’t. I'm not saying it's wrong, but I just didn't feel like a solution I would like to implement.

So to me, and to solve the problems I was having at the beginning of the post, without going against my intuitions, is to still use a hierarchy, however it won’t be a monolithic hierarchy like the ones I used before, but rather a polylithic one (I couldn’t find a word opposite to monolithic), which consists of several, smaller trees.

The following example shows what I mean (this is inspired by an example I found in Game Engine Architecture, Chapter 14).

I would have a small tree for vehicles. The root vehicle class would have a rendering component, a collision component, position component etc..

Then a tank, a subclass of vehicle would inherit those components from it, and be given it's own "cannon" component.

The same goes for the Characters. A character would have it's own components, then the Player Class would inherit it, and be given an Input controller, while other enemy classes would inherit from the Character class and be given an AI controller.

I don't really see any problems with this design. Despite not using a pure Entity Controller System, the problem with the bubbling up effect, and the large root class is solved by using a multi-tree hierarchy, and the problem of the heavy, code duplicating leafs is gone since the leafs don't have any code to begin with, just components. If a change needs to be done to the leaf level, then it's as simple as changing a single component, instead of copy pasting the code everywhere.

Of course, being as inexperienced as I am, I did not see any problems when I first started using the single hierarchy, inheritance heavy model, so if there are problems with the model that I'm currently thinking of implementing, I wouldn't be able to see it.

Your opinions?

P.S: I am using Java, so using multiple inheritance to implement this instead of using normal components is not possible.

P.P.S: Intercomponent communications will be done by linking dependent components to each other. This will lead to coupling, but I think it's an ok trade off.

\$\endgroup\$
6
  • 2
    \$\begingroup\$ This all seems fine to me. Is there a specific example in your hierarchy or entity system that "smells" to you? In the end, it's all about getting the game done more than some sense of purity. \$\endgroup\$
    – drhayes
    Aug 20, 2012 at 7:25
  • \$\begingroup\$ I don't, but like I said, I barely have any experience and I am far from the best judge for this. \$\endgroup\$ Aug 20, 2012 at 7:53
  • 3
    \$\begingroup\$ I've voted to close this question because it's subjective and open to wide discussion. I appreciate it was asked from a sincere position - but choosing how to proceed here is entirely a matter of personal opinion. The only real downside of fixing your components into a subclass is that the arrangement of components are not changeable at runtime - but that must surely be apparent to you and it's a choice you make. \$\endgroup\$
    – Kylotan
    Aug 20, 2012 at 10:27
  • 4
    \$\begingroup\$ I voted to close too. It's a good and well-written question, but not appropriate for GDSE. You might try reposting this at GameDev.net. \$\endgroup\$ Aug 20, 2012 at 21:05
  • \$\begingroup\$ As written, with the question being 'Your opinions?', it is indeed open-ended and unanswerable. However, it is answerable if you answer it as if the question was 'Are there any gaping traps that I could fall into without noticing?' (At least, if you think that there is in fact any empirical difference between various architectures.) \$\endgroup\$ Aug 21, 2012 at 3:22

3 Answers 3

8
\$\begingroup\$

Consider this example:

You're making an RTS. In a fit of complete logic, you decide to make a base class GameObject, and then two subclasses, Building and Unit. This works just fine, of course, and you end up with something that looks like this:

  • GameObject
    • ModelComponent
    • CollisionComponent
  • Building
    • ProductionComponent
  • Unit
    • AimingAIComponent
    • WeaponComponent
    • ParticleEmitterComponent
    • AnimationComponent

Now every subclass of Unit you make already has all the components you need. And as a bonus, you have a single place to put all that tedious setup code that news up a WeaponComponent, connects it to an AimingAIComponent and a ParticleEmitterComponent—wonderful!

And of course, because it still factors logic out into components, when you eventually decide that you want to add a Tower class that's a building but has a weapon, you can manage it. You can add an AimingAIComponent, a WeaponComponent, and a ParticleEmitterComponent to your subclass of Building. Of course, then you have to go through and dig out the initialization code from the Unit class and put it somewhere else, but that's no big loss.

And now, depending on how much foresight you had, you may or may not end up with subtle bugs. Turns out there might've been some code elsewhere in the game that looked like this:

if (myGameObject instanceof Unit)
    doSomething(((Unit)myGameObject).getWeaponComponent());

That silently doesn't work for your Tower building, even though you really wanted it to work for anything with a weapon. Now it has to look something like this:

WeaponComponent weapon = myGameObject.getComponent(WeaponComponent.class);
if (weapon)
    doSomething(weapon);

Much better! It occurs to you after changing this that any of the accessor methods you've written could end up in this situation. So the safest thing to do is strip them all out, and access every component via this one getComponent method, which can work with any subclass. (Alternately, you can add every single kind of get*Component() to the superclass GameObject and override them in subclasses to return the component. I'll assume the first one, though.)

Now your Building and Unit classes are pretty much just bags of components, without even accessors on them. And no fancy initialization either, because most of that needed to be dragged out to avoid code duplication with your one special-case other object somewhere.

If you follow this to the extreme, you always end up making your subclasses completely inert bags of components, at which point there isn't even any point having the subclasses around. You can gain almost all the benefit of having a class hierarchy with a method hierarchy that creates the proper components. Instead of having a Unit class, you have a addUnitComponents method which makes an AnimationComponent and also calls addWeaponComponents, which makes an AimingAIComponent, a WeaponComponent, and a ParticleEmitterComponent. The result is that you have all the benefits of an entity system, all the code reuse of a hierarchy, and none of the temptation to check instanceof or cast to your class type.

\$\endgroup\$
3
  • \$\begingroup\$ Well said. Adding to this I think the ideal solution is to initialize each entity with a script or with descriptor files. I use text files for entity initialization. It's fast and allows non programmers to test different parameters. \$\endgroup\$
    – Coyote
    Aug 21, 2012 at 7:23
  • \$\begingroup\$ Wow reading your post gave me a nightmare! Of course, I do mean that in a good way, seeing as you opened my eyes to what kind of nightmare I might end up with! I wish I could reply more to such a detailed answer, but there's not much to add really! \$\endgroup\$ Aug 23, 2012 at 12:53
  • \$\begingroup\$ On a more simple way. You end using Inheritance as poor's man Factory pattern. \$\endgroup\$
    – Zardoz89
    Jul 23, 2016 at 11:45
2
\$\begingroup\$

Composition over Inheritance is the OOP terminology (at least the way I learned/was taught it). To chose between composition and inheritance you say out loud "Car is a type of wheel" (inheritance) and "Car has wheels" (composition). One should sound more correct than the other (composition in this case), and if you can't decide, default to composition until you decide otherwise.

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

When it comes to integrating components based systems to existing games based on game objects there is an article at cowboy programming http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/ which might give you some pointers on the way the transition can be made.

As to issues, your model will still need to handle the player differently from another enemy. You won't be able to switch status (ie player becoming AI controlled) when a player disconnects or in special cases without handling him differently from the other characters.

Apart from the heavy reuse of components across diferent entities, the idea of component based games is the uniformity of the entire system. Each entity has components that can be attached and detached at will. All the components of the same kind are handled exactly the same way with a set of calls established by the interface (base component) of each kind (position, rendered, script...)

Mixing game objects inheritance with a component based approach brings you some advantages of the component based approach with drawbacks from both approaches.

It can work for you. But I woudn't mix both outside of a transition period from one architecture to the other.

P.S. written on a phone so I have a hard time linking to external resources.

\$\endgroup\$
2
  • \$\begingroup\$ Thank you for your reply even though you were on the phone! I do understand what you mean. The move component based things are, the more flexibility I have to alter things. It's the reason why I'm going to go ahead and try a composition approach with minimal inheritance. (Even more than the one I proposed.) \$\endgroup\$ Aug 23, 2012 at 12:51
  • \$\begingroup\$ @MidoriRyuu avoid all inheritance in the entity objects. You are lucky enough to be using a language with reflection (and introspection) built-in. You can use files (txt or XML) to initialize your objects with the right parameters. It's not too much work and it will allow for enhanced game fine tuning without recompiling. But keep the Entity class, at least for inter-component communication and other utility tasks. P.S. still on the phone :( \$\endgroup\$
    – Coyote
    Aug 23, 2012 at 19:55

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