5

So I've been doing a lot of research into game engines, and Entity Component System (ECS) seems to be the most flexible and extendable design to use.

Just to summarize, in ECS the basic idea is that you have Entities which are just containers for Components, and different Components correspond to different functionality, but they only store data. So for example, in a tower defense game, you could have a tower entity which has a moveable component, but all the component really stores would be the towers current direction and velocity.

The actual logic of moving the tower is controlled in a System. What a System does is it iterates through all the entities that have specific components, and modifies them accordingly. So you would have a Movement System which would only look at the Movable Entities (it has a moveable component), and update the data accordingly.

So all this makes sense to me in terms of how to design a Game Object that stores all the info about a Game. My question is how would you incorporate custom user defined rules into this model? Because what I have is a game engine, it needs to be able to handle specific user defined rules which may vary from Game to Game, or even from Level to Level within a Game.

For example, let's say I want a rule saying that I want all towers to move, except when it's within a certain range of an enemy. Where would this logic reside? If it resides in the Movement system, that would me that I would need to create a new movement system for each game which is not how game engines are supposed to work right? The whole idea is that you feed it any game and the systems can handle it. Would I need a separate "Rules" system?

2 Answers 2

3

To begin with, a caveat: even more than other domains of programming, every design decision in game development is a tradeoff. The "right" answer is "whatever works for the game you are making."

Okay. There are a few approaches we can take:

  1. If there are a small, known set of general behaviors, write them inline and allow the user to tweak parameters. (i.e., which enemies does this tower avoid, how far away does it need to be, etc.) This is the most straightforward and maintainable approach, but it scales poorly the more different behaviors you have.

  2. Functions can be data! In C, this is a function pointer, other languages have equivalents. The code that creates the entity is responsible for giving it a function telling it how to act.

In C it'd look something like this:

// Define a function pointer type.
typedef void BehaviorFunc(Entity * this);

struct FooComponent {
    BehaviorFunc * my_behavior;
    // Other data as needed...
}

// User code:
void MyBehaviorFunc(Entity * this) {
    DoTheThing();
}
// ...
{
    FooComponent * f = AddFooComponent();
    f->my_behavior = MyBehaviorFunc;
}

// Update:
void UpdateFooComponent(FooComponent * f) {
    // stuff
    f->my_behavior(GetEntityFromComponent(f));
    // more stuff
}

We actually have other options here as well. If you need to allow non-programmers to define behaviors, you could replace the function pointer with a behavior tree, compiled script code, etc. All of these are much more complicated, though, so don't bother unless you actually need the extra flexibility. Keep in mind that the more general you make the system, the harder it is to implement (and optimize), for both the engine and client code.

0

This question was asked a few years back, but I'm actually going through the process of building an Entity Component System (ECS) architecture myself and may have some insight that you and the community may find helpful.

Note: framework is short for ECS framework and both are used in place of game engine. ECS frameworks are just a specific type of game engine. In addition, there is more than one way to crack an egg and the same is true for ECS framework design. There is not one definition on which ECS frameworks are built. There are however some generally accepted characteristics that guide their design. I try to stick to just the characteristics when possible. Some things I present here may be more flexible when talking about a different ECS architecture. Being such an old question, the OP may not be around to clarify so I'm just taking a stab at the kind of ECS architecture the OP is asking about based on the wording of the question.


Question/Comment 1

"For example, let's say I want a rule saying that I want all towers to move, except when it's within a certain range of an enemy. Where would this logic reside?"

Rules related to movement would most likely be implemented as a special case of your tower movement logic. As an example of one way to do it, see below.

class TowerMovementSystem
{
    public void update()
    {

        .
        .
        .

        var enemies = worldManager.findLocalEnemies(positionComponent);

        if(enemies.empty())
        {
            // Move towers...
        }
    }
}

There are a lot of details missing from the above example, but the important takeaway is the logic for movement goes into a system. The update() function gets executed by some higher level framework code such as the game loop or a system management utility. That means the update() function is, most likely, never called by code written by the game developer, despite the system class being written by the game developer.


Question/Comment 2

"If it resides in the Movement system, that would me that I would need to create a new movement system for each game..."

Correct. Movement is different per game. Mario moves very different from a space ship in Asteroids. The game designer is responsible for defining that movement.


Question/Comment 3

"... which is not how game engines are supposed to work right? The whole idea is that you feed it any game and the systems can handle it."

I understand where you are coming from with this question. A variation of this question plagued my mind when I first got into hobby game development. I eventually came to an answer partly through experience using several game engines over the years, but also from evaluating the idea of you are getting at when you say "feed it any game".

What is a game in a technical sense? I'm not trying to get philosophical or anything here, but we need a working definition so we can say for certain what we are feeding the framework. To me, a game is a collection of entities, that change state through interactions with players and other entities, where the interactions are constrained by some set of rules.

Here are some examples to illustrate.

Pong - The Pong Ball

The Pong ball (entity) changes position (state change) based on its velocity. It moves in a strait line (rule constraint) unless bouncing off a wall (rule constraint)(state change) or paddle (rule constraint)(state change).

Mario - 2D Goomba

The Goomba (entity) changes position (state change) based on its velocity. It moves in one direction, left or right (rule constraint), in a strait line (rule constraint). When it bumps into an obstacle (rule constraint) it changes direction (state change) and continues to move. It dies (state change) when stepped on (rule constraint) by Mario.

All of the above maps very nicely into the ECS architecture (One reason why ECS architecture is becoming very popular for game development).

Definition Concept -> ECS Architecture Concept -> Examples
Entities -> Entities -> Pong ball, Mario Goomba
States -> Components -> PositionComponent, VelocityComponent, LifeComponent
Rule Constraint Sets -> Systems -> PongBallMovementSystem, GoombaMovementSystem, MarioMovementSystem

So what we feed to the framework are entities, components, and systems. Systems are not a part of the framework, they are feed or registered to the framework. Systems implement the rule sets specific to each game (or levels) and the framework operates them to drive interactions that will cause state changes for your entities. They are implemented external to the framework. This could be by the game developer (most likely case) or may be implemented by a framework developer and shipped as an helpful addon package for game developers to use.

If the framework developer supplies some pre-made systems, the issue becomes they can only guess what type of games will be made with their software. This restricts them to only supplying generic systems that will not have custom rules like "octupple jump" or "stop when in range of enemies" (unless they provide source code that can be modified and re-built or build in some scripting capabilities which is probably more trouble than its worth).


Question/Comment 4

"Because what I have is a game engine, it needs to be able to handle specific user defined rules which may vary from Game to Game, or even from Level to Level within a Game."

That statement is incorrect. The framework provides the mechanisms for you to define your game, but never knows any specifics about your game such as game rules or level constraints. Those are things that go in the systems we talked about earlier. The framework is like the foundation on which to build your game. The framework addresses concerns like

  • Registration/De-registration/Creation/Destruction of
    • Entities
    • Components
    • Systems
  • Execution of systems.
  • Inter-framework communication (system-system communication, logging, etc.)
  • How the game loop progresses
    • Event driven
    • Time driven
      • Fixed timestep
      • Variable timestep
  • Entity definition
    • Object with data
    • Integer ID only
  • How to store components
    • Store copies in each system keyed with entity IDs
    • Store in an entity object
    • Store in component manager with entity IDs
  • How Systems communicate
    • Event messages
    • Callbacks
    • Observer pattern
    • No communication allowed
  • Many more...

As you can see, the framework does not address concerns for any particular game or game rules. It addresses meta-concerns necessary to build a game using ECS architecture.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.