9
\$\begingroup\$

I'm fairly new to the idea of entity systems, having read a bunch of stuff (most usefully, this great blog and this answer).

Though I'm having a little trouble understanding how something as simple as being able to manipualate the position of an object by an undefined number of sources.

That is, I have my entity, which has a position component. I then have some event in the game which tells this entity to move a given distance, in a given time.

These events can happen at any time, and will have different values for position and time. The result is that they'd be compounded together.

In a traditional OO solution, I'd have some sort of MoveBy class, that contains the distance/time, and an array of those inside my game object class. Each frame, I'd iterate through all the MoveBy, and apply it to the position. If a MoveBy has reached its finish time, remove it from the array.

With the entity system, I'm a little confused as how I should replicate this sort of behavior.

If there were just one of these at a time, instead of being able to compound them together, it'd be fairly straightforward (I believe) and look something like this:

PositionComponent containing x, y

MoveByComponent containing x, y, time

Entity which has both a PositionComponent and a MoveByComponent

MoveBySystem that looks for an entity with both these components, and adds the value of MoveByComponent to the PositionComponent. When the time is reached, it removes the component from that entity.

I'm a bit confused as to how I'd do the same thing with many move by's.

My initial thoughts are that I would have:

PositionComponent, MoveByComponent the same as above

MoveByCollectionComponent which contains an array of MoveByComponents

MoveByCollectionSystem that looks for an entity with a PositionComponent and a MoveByCollectionComponent, iterating through the MoveByComponents inside it, applying/removing as necessary.

I guess this is a more general problem, of having many of the same component, and wanting a corresponding system to act on each one. My entities contain their components inside a hash of component type -> component, so strictly have only 1 component of a particular type per entity.

  1. Is this the right way to be looking at this?

  2. Should an entity only ever have one component of a given type at all times?

\$\endgroup\$
6
  • 1
    \$\begingroup\$ Sounds kind of like the MoveBy functionality is kind of just a velocity? It sounds like you're on the right track. For your second question, there are plenty of different implementations of entity/component systems. The one described in my answer you linked would only have one component of a given type. \$\endgroup\$
    – House
    Commented Nov 25, 2012 at 8:16
  • \$\begingroup\$ Sort of, but the difference being that this velocity is only valid from one time to another, and many of them can be compounded together at once. I think I just needed some reassurance, I've been strict (anal, almost) OO for my games in the past -- which years later on the same project, has crippled our production speed -- and this is scarily unfamiliar territory ;). Great answer on the other post by the way, helped clear up some things \$\endgroup\$
    – Sticky
    Commented Nov 25, 2012 at 17:22
  • \$\begingroup\$ I do it like this: I have PlayerInputComponent and AIInputComponent (or systems) that will tell MobileBehaviorComponent that on keyboard click or on AI thinking that mobile should move somewhere, MobileBehaviorComponent will store that it should move somewhere (it has FSM inside for mobile actions) and some system will move it. Your granularity is just too much, with higher level components, like Transform, Model, Light, Mob everything works just as well. Also i never needed to remove components - i think of them more like something that describes game object so it cannot just disappear. \$\endgroup\$
    – Kikaimaru
    Commented Nov 25, 2012 at 17:40
  • \$\begingroup\$ This particular MoveBy example was just an example. The question was more about how you compound things together like that. If I need to specifically say 'move by x=5 and y=6 in 5 seconds' 'move by x=10 y=2 in 10 seconds', at the same time, is this how I would do it? \$\endgroup\$
    – Sticky
    Commented Nov 25, 2012 at 18:08
  • \$\begingroup\$ What do you mean by "compounded together"? Like adding velocities? So if you compounded move x by 10 in 2 seconds and move x by -10 in 2 seconds the entity would stand perfectly still? \$\endgroup\$ Commented Nov 26, 2012 at 0:59

2 Answers 2

6
\$\begingroup\$

For your scenario, we typically add three components to a game object:

  1. TransformComponent (position, orientation, scale)
  2. VelocityComponent (speed, direction)
  3. ControllerComponent

When game objects need some type of AI functionality such as moving along a path as you described, we assign an AIController to it's list of components. AIControllers are really nothing more beyond a wrapper that steps a Behavioral Tree. The behavior tree is where we design the actual functionality we want to have the game object perform such as:

BehaviorTree* tree(new SequentialNode());
tree->addChild(new MoveToNode(x,y,z));
tree->addChild(new WaitNode(30));
tree->addChild(new MoveToNode(a,b,c));
tree->addChild(new WaitNode(30));
gameObject->addComponent(new AIController(tree));

The AI subsystem manages AIControllers and so that subsystem ticks the controller which in turn steps the Behavior Tree. The MoveToNode() looks at the present position/orientation, calculates a direction vector and speed to where you want to move to based on it's constructor arguments and sets the values on the velocity component. The movement system is responsible for reading movement components with values and applying physics thus updating the position/orientation accordingly.

The above code simply moves a game object from spawn location to x,y,z in world space, then waits a minimum of 30 seconds, then moves the game object to location a,b,c and then waits another 30 seconds. Once the wait is over, the behavior sequence has finished, so it repeats from the start.

This allows you to easily define whatever AI functionality you need all self contained in the AI subsystem with minimal impact to your Entity subsystem. It also allows you to keep your entity system component list lean without too much granularity too.

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

An option is to add controllers to your design. Entities own data to represent position (in the case of my engine they have data that remember the previous positions too, so I can know the velocity vector and if they are being moved or teleported), but they don't know nothing about physics or AI. Controllers move entities and you can have many controllers affecting the same entity or one controller affecting various entities.

For example: create a base Controller class with a run() method, or if you don't like the name call it think(), update() or tick(). Then you inherit from it and create a MoveController, NPCController, PlayerInputController (for the player entity), PhysicController; then you implement the run() method. I would put your MoveByComponent in the MoveController and not in Entity.

These Controllers can be instantiated by each Entity if they hold data specific of an Entity. They can be destroyed or reseted for reuse latter. Also you can use a Controller for move a group of entities, in a RTE game for example, if you need to move various units as a group, have a controller by each unit may hurt game performance, then you can simply assign all the units to a GroupController or LegionController and let it move the units as part of a organized group. When fighting, if the game allows individual unit behavior, and probably most games do, you will have to switch to a UnitController but it's better to do that only when needed than from the beginning.

In my developing game I have a MoveController that moves entities following a path, one MoveController exists for each NPC and the player character. Occasionally one is created for boxes or rock that the player can push. The PhysicController, only one instance, that will check positions of all entities assigned to it, if some entity is colliding another assigned entity the resulting position of both is calculated (it actually does more than that but you get the idea). The NPCController is the AI, one instance per NPC. It checks the situation of the NPC and decides where to move, then push the path to a MoveController, that actually moves the NPC. Controllers have a priority, so I can determine in advance their order, the PhysicController is the last to execute.

I advocate for controllers but is not the only "correct" option. For example I remember an Entity interface in Cafu engine that have the think() method in the Entity itself, the user of the class must inherit from Entity and implement think(), I remember a derived class called CompanyBot (that comes with the example game) that do some collision check in that method, as it is called "think" we can assume AI code is expected to be there too. While NeoAxis engine (last time I looked into it) have AI and physics separated from the entities.

There exists a Controller pattern that I have listened about. Maybe you should search for it, and that probably is not exactly what I'm talking about here but sounds like a good solution too.

\$\endgroup\$
3
  • \$\begingroup\$ That's basically the OO design that we already have right now. An Entity, with derivatives (Character, Monster) etc., I've been leading a team of us that have been working on this game full time for almost 2 years, and with everybody changing things at will, it's become a horrible, horrible codebase -- and is starting to take an embarrassingly long time to get new features shipped. The Entity System idea seems to be exactly what I'm looking for, so while your answer isn't quite relevant, you should read up on the links at the top of the question yourself, see if they can help you out :) \$\endgroup\$
    – Sticky
    Commented Nov 25, 2012 at 17:13
  • \$\begingroup\$ @Sticky I have to admit that the Node System plus Entity made of components is a clever way of represent the different needed systems than my suggested controllers approach that is like a less evolved version. You really don't need my answer after all. \$\endgroup\$ Commented Nov 25, 2012 at 20:30
  • \$\begingroup\$ No worries. The OO way does have its advantages, but things get ugly, fast \$\endgroup\$
    – Sticky
    Commented Nov 25, 2012 at 20:43

You must log in to answer this question.

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