2
\$\begingroup\$

So, I decided to see what the Entity/Component system of game development was all about. I really liked it. So, I decided to implement my current game with it.

My problem: Unique Behaviour with the system. From what I have seen, the way to implement Unique Behaviour for a entity is to Create a unique Component, and a Unique System that only accepts Entities with that Component. This seems to be a lot of code, for what could be a very small feature.

My Solution: Have entities with "hooks" in them, so that they can define their own unique behaviour in them. They would still have the major things done for them by systems, such as Health, Rendering, and Movement.

e.g.:

public abstract class EntityLiving extends Entity{

    /**
     * Called when a entity is spawned in
     * @param map
     */
    public void onSpawn(Map map) {this.map = map;}

    /**
     * Called when an entity is killed
     * @param map
     */
    public void onDeath(Map map) {}

My Question: Is this bad programming practice? Could this be done in a 'better' way? I realize that this question is extremely subjective, but I would like some professional opinions.

EDIT: By better I mean, in order of priority:

  1. Less Code for this scenario
  2. Code Reusability
  3. Code Efficency
\$\endgroup\$
3
  • \$\begingroup\$ What do you mean by 'better'? Please describe what you think is wrong with the current strategy that needs to be 'better'. If you define 'better' it makes the question far less subjective and more answerable. \$\endgroup\$
    – House
    Commented Dec 11, 2014 at 2:16
  • \$\begingroup\$ @Byte56 Edited. Thanks for the push to define. Didn't think of defining it. \$\endgroup\$
    – chbachman
    Commented Dec 11, 2014 at 2:22
  • 3
    \$\begingroup\$ Yet another "I'm using ECS and I can't do something, please validate my design" question? If it doesn't fit your game, don't use it - it's that simple. ECS is never about having less code anyway (which is indeed a great goal, btw). \$\endgroup\$
    – snake5
    Commented Dec 11, 2014 at 5:37

2 Answers 2

2
\$\begingroup\$

Entity/Component systems do allow for unique behavior. This will depend on how you design your components. Components contain data, and systems can change how they process components based on that data. There's no best practice when it comes to designing these things. It's going to depend on the requirements for your game and very much on your coding style and personal preference.

In an extreme example of unique behavior, you could have a component that simply contains some kind of script. The system for that component would read and execute that script. Since the script is contained in the data, it can be different for every entity that has that component. This is an extreme example because you could essentially implement your entire game just using that one component and system. But for usability's sake, you'd want to expand that into slightly more specific use cases.

For example, you could have a Spawn component that defines a limited set of spawn behaviors and the system will simply enumerate the options and perform the defined actions. You have lots of flexibility when it comes to creating components and systems. I'm sure you can think of numerous ways to create a component or system that doesn't require you to create a new component and system for each behavior you'd like.

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

I would normally just recommend avoiding an ECS and using a more flexible component model that isn't as constraining or filled with as much boilerplate. You can totally put polymorphic logic into an ECS, though, without altering the ECS design itself.

One possible approach is to create a LogicComponent and corresponding LogicSystem. This component's data would be an owned pointer to a polymorphic ILogicBehavior interface class or the like. The system iterates the components and invokes an OnTick virtual member function. Your data for game objects would describe which ILogicBehavior sub-class to actually load and instantiate and deserialize into, just like with other components.

The behaviors can still be allocated in a pool. The LogicSystem can sort components by their behavior's concrete type, giving you most of the same CPU cache access pattern advantages as a pure ECS.

Because it's only LogicComponent types that have a behavior that needs the OnTick function called you avoid the overhead of more naive component-based architectures that invoke such a function for every single active component in the game. With the LogicSystem approach, you don't need to make any changes to your other components or systems or core ECS architecture at all.

This approach is roughly equivalent in terms of object composition flexibility as a ScriptComponent and related system, which you might have as well. The script execution system will certainly be no more efficient than the logic component/system I just described (even if you go the naive implementation route) and will likely be far, far less efficient; you're still coming out ahead by having native-code polymorphic logic components than you are by shoving game logic out into scripts.

\$\endgroup\$

You must log in to answer this question.

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