10
\$\begingroup\$

I'm trying to design a component-based entity system for learning purposes (and later use on some games) and I'm having some troubles when it comes to updating entity states.

I don't want to have an update() method inside the Component to prevent dependencies between Components.

What I currently have in mind is that components hold data and systems update components.

So, if I have a simple 2D game with some entities (e.g. player, enemy1, enemy2) that have Transform, Movement, State, Animation and Rendering components I think I should have:

  • A MovementSystem that moves all the Movement components and updates the State components
  • And a RenderSystem that updates the Animation components (the animation component should have one animation (i.e. a set of frames/textures) for each state and updating it means selecting the animation corresponding to the current state (e.g. jumping, moving_left, etc), and updating the frame index). Then, the RenderSystem updates the Render components with the texture corresponding to the current frame of each entity's Animation and renders everything on screen.

I've seen some implementations like Artemis framework, but I don't know how to solve this situation:

Let's say that my game has the following entities. Each entity have a set of states and one animation for each state:

  • player: "idle", "moving_right", "jumping"
  • enemy1: "moving_up", "moving_down"
  • enemy2: "moving_left", "moving_right"

What are the most accepted approaches in order to update the current state of each entity? The only thing that I can think of is having separate systems for each group of entities and separate State and Animation components so I would have PlayerState, PlayerAnimation, Enemy1State, Enemy1Animation... PlayerMovementSystem, PlayerRenderingSystem... but I think this is a bad solution and breaks the purpose of having a component-based system.

As you can see, I'm quite lost here, so I'd very much appreciate any help.

EDIT: I think the solution to make this work as I intend is this one:

You make statecomponent and animationcomponent generic enough to be used for all entities. The data they contain will be the modifier for changing things like which animations are played or which states are available. – Byte56

Now, I'm trying to figure out how to design these 2 components generic enough so I can reuse them. Might having an UID for each state (e.g. walking, running...) and storing animations in a map into the AnimationComponent keyed by this identifier be a good solution?

\$\endgroup\$
6
  • \$\begingroup\$ I assume you've seen this: State changes in entities or components? Is your question fundamentally different from that one? \$\endgroup\$
    – House
    Commented Oct 26, 2012 at 20:35
  • \$\begingroup\$ @Byte56 Yes, I read that some hours ago. The solution you suggested there is similar to the idea that I've exposed here. But my problem comes when the StateComponent and AnimationComponent are not the same for all entities whithin the system. Should I split that system into smaller systems that process groups of entities that has the same possible states and animations? (see last part of my original post for better clarification) \$\endgroup\$
    – miviclin
    Commented Oct 26, 2012 at 21:24
  • 1
    \$\begingroup\$ You make statecomponent and animationcomponent generic enough to be used for all entities. The data they contain will be the modifier for changing things like which animations are played or which states are available. \$\endgroup\$
    – House
    Commented Oct 26, 2012 at 21:54
  • \$\begingroup\$ When you talk about dependency, do you mean data dependency or execution order dependency? Also, in your propose solution, the MovementSystem now has to implement all the different ways something can move? This looks like it is breaking the idea of the component-based system... \$\endgroup\$
    – ADB
    Commented Oct 26, 2012 at 22:06
  • \$\begingroup\$ @ADB I'm talking about data dependency. In order to update the animation (e.g. change from move_right animation to move_left animation) I need to know the current state of the entity and I don't see how to make these 2 components more generic. \$\endgroup\$
    – miviclin
    Commented Oct 26, 2012 at 22:20

3 Answers 3

5
\$\begingroup\$

IMHO the Movement component should hold the current state (Movement.state) and the Animation component should observe changes of Movement.state and update its current animation (Animation.animation) accordingly, using a simple lookup of state id to animation (as suggested at then end of the OP). Obviously this means Animation will depend on Movement.

An alternative structure would be to have a generic State component, which Animation observes, and Movement modifies, which is basically model-view-controller (state-animation-movement in this case).

Another alternative would be to have the entity dispatch an event to its components when its state changes. Animation would listen to this event and update its animation accordingly. This eliminates the dependency, although you could argue that the dependent version is a more transparent design.

Good luck.

\$\endgroup\$
2
  • \$\begingroup\$ So Animation observes State and State observes Movement... Dependencies are still there but I might give it a try. Would the last alternative be something like this: Movement notifies changes to the entity and the entity dispatches an event to State, and then the same process would be repeated for State and Animation? How could this approach impact performance? \$\endgroup\$
    – miviclin
    Commented Oct 28, 2012 at 23:58
  • \$\begingroup\$ First case: Movement would control State (not observe). Last case: Yeah Movement would do entity.dispatchEvent(...); or so, and all other components listening to that type of event will receive it. Performance is ofcourse worse than pure method calls, but not much. You can pool event objects for example. Btw, you don't have to use the entity as the "event node", you could use a dedicated "event bus" as well, leaving your entity class completely out of it. \$\endgroup\$
    – Torious
    Commented Oct 29, 2012 at 0:14
2
\$\begingroup\$

About your problem, if the STATE is only used in Animations, then you don't even need to expose that to other Components. If it has more than one use, then you need to expose it.

The system of Components/Subsystem that you describe feels more hierarchy-based than component-based. After all, what you describe as components are in fact data structures. It doesn't mean it is a bad system, just that I don't think it fits the component-based approach too well.

As you noted, dependencies are a big problem in component-based systems. There are different ways to deal with that. Some require each component to declare their dependencies and do a strict check. Others query for components implementing a specific interface. Still others pass reference to the dependant components when they instantiate each of them.

Independently of the method you use, you will need a GameObject of some sort to act as collection of Components. What that GameObject provides can vary a lot and you can simplify your inter-component dependencies by pushing some often-used data to the GameObject level. Unity does that with the transform for example, force all game object to have one.

Concerning the problem you ask of different states/animation for different game objects, here's what I would do. First, I wouldn't get too fancy at this stage of the implementation: only implement what you need now to get it working, then add bells and whistles as you need them.

So, I'd start with a 'State' component: PlayerStateComponent, Enemy1State, Enemy2State. The state component would take care of changing the state at the appropriate time. State is something pretty much all your objects will have, so it can reside in the GameObject.

Then, there would be an AnimationCompoment. This would have a dictionary of animations keyed to the state. In update(), change the animation if the state changes.

There's a great article about building framework that I can't find. It said that when you don't have experience in the domain, you should pick one problem and do the simplest implementation that solves the current problem. Then you add another problem/use-case and expand on the framework as you go along, so it grows organically. I really like that approach, particularly when working with new concept as you are doing.

The implementation I proposed is quite naive, but here are some possible improvements as you add more use-case:

  • replace the GameObject variable with a dictionary. Each component use the dictionary to store values. (make sure to handle collision properly...)
  • replace the dictionary of plain values with references instead: class FloatVariable() { public value [...] }
  • Instead of multiple state component, create a generic StateComponent in which you can build variable state machines. You need to have a generic set of condition upon which a state can change: key presses, mouse input, variable changes (you can tie that to the FloatVariable above).
\$\endgroup\$
1
  • \$\begingroup\$ This approach works, I implemented something similar a year ago, but the problem with it is that almost every component depends on other components, so it seems less flexible to me. I also thought about pushing the most common components (e.g. transform, render, state...) into the entity but I think this breaks the purpose of components because some of them are tied to the entity and some entities may not need them. That's why I'm trying to redesign it with systems being responsible for updating the logic so components would know nothing about each other as they don't update themselves. \$\endgroup\$
    – miviclin
    Commented Oct 27, 2012 at 11:14
0
\$\begingroup\$

In addition to the answer of ADB you could use http://en.wikipedia.org/wiki/Dependency_injection, which helps when you need to construct a lot of components via passing them as references to their constructors. Obviously they will still depend on each other (if that is required in your code base), but you can put all that dependency in one place where the dependencies are setup and the rest of your code does not need to know about the dependency.

This approach also works well if you use interfaces because each component class just requests what it needs or where it needs to be registered and only the dependency injection framework (or the place where you set everything up, usually the app) knows about who needs what.

For simple systems you might get away without using DI or clean code, your RenderingSystem classes sounds like you need to call them statically or at least have them available in each component, which pretty much makes them dependent on each other and hard to change. If you are interested in a more clean approach check the links of the DI wiki link above and read about Clean Code: http://clean-code-developer.com/

\$\endgroup\$
1
  • \$\begingroup\$ I already have one system where components are quite dependant of each other. I made heavy use of dependency injection there, and although I prefer it over deep hierarchies, I'm trying to create a new one to avoid component coupling if it were possible. I wouldn't be calling anything statically. I would have a ComponentManager that every system have access to (every system should have a reference to it), and the RendererSystem would get all the animation components from the component manager and render the current state of each animation. \$\endgroup\$
    – miviclin
    Commented Oct 27, 2012 at 20:47

You must log in to answer this question.

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