0
\$\begingroup\$

I want to start with an (easy) Entity Component System. I have a question regarding the messaging between Components.

Let's say I have a RenderComponent. This component needs 2 integer values x and y and probably a Sprite to render. Now I have 3 other Components:

  • TransformComponent with 5 doubles: x, y, width, height and rotation.
  • MovementComponent with 2 doubles: velX and velY.
  • AnimationComponent with an array of Sprites.

Now I want to render my Entity.

How do I collect the Data from the different Components to render my Sprite? All these informations have to enter the RenderingComponent at the same time. Does someone have an idea on how to accomplish an efficient ECS?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ What is the job of your system(s)? What is the difference between your RenderComponent x/y and the Transform's x/y? Your renderer does not need to know anything about movement. In what Transform is related to width and height? To me, the System gathers the components, not components themselves. Your ECS design should probably be a bit more explained because it's difficult to give you a good answer. \$\endgroup\$
    – Vaillancourt
    Jul 6, 2015 at 17:23

3 Answers 3

1
\$\begingroup\$

Templating and metaprogramming are your friends here.

What I did for my engine was implement a method like Unity: GameObjectInstance.GetComponent<ComponentType>(). And make sure that every Component has access to the GameObject that it's attached to. This way you can easily say in MovementComponent

void Update()
{
    //Move game object
    transform = gameObject.GetComponent<TransformComponent>();
    transform.position += Vector(xVel, yVel);

    //Animate sprites
    animator = gameObject.GetComponent<AnimationComponent>();
    animator.AnimateMoving();
}

It's best to model a component system off of something like Unity or Unreal which is proven to work unless you have a reason for doing something experimental.

\$\endgroup\$
3
  • \$\begingroup\$ I prefer to pass the GameObject to the Update method to avoid storing a reference on the component itself. You COULD add it to the component if you wanted to, but when you have tens of thousands of component instances its a big waste of space to store the reference to the game object on all components. \$\endgroup\$ Jul 6, 2015 at 19:45
  • \$\begingroup\$ Unity is not an ECS architecture; it's a component based architecture. \$\endgroup\$
    – Vaillancourt
    Jul 6, 2015 at 19:59
  • \$\begingroup\$ This is the easiest solution, but this one forces dependencies for the Components. A MovementComponent needs a AnimationComponent and a TransformComponent (Yeah, it sounds correct, but e.g. a Platform can move, and does not animate) \$\endgroup\$
    – Raildex
    Jul 7, 2015 at 7:41
1
\$\begingroup\$

You could try creating a System architecture. Like components are added to entities and entities are added to an engine, the engine could also contain a collection of Systems.

A System would iterate through the entities in the engine and for each entity that contains a TransformComponent, MovementComponent and AnimationComponent, it gathers all necessary data needed to render your entity.

RenderSystem - on Update:

for (Entities in Engine) {
    if (Entity contains TransformComponent, MovementComponent, AnimationComponent) {
        // Render the entity
    }
}

This same pattern can be seen in entity frameworks such as Artemis and Ashley. With Ashley, you can create a system which only updates entities that contain specific components using Family. Here's an example (Java):

public class AnimationSystem extends IteratingSystem {

    public AnimationSystem() {
        super(Family.all(
                TransformComponent.class,
                MovementComponent.class,
                AnimationComponent.class
        ).get());
    }

    @Override
    protected void processEntity(Entity entity, float deltaTime) {
        TransformComponent transform = entity.getComponent(TransformComponent.class);
        MovementComponent movement = entity.getComponent(MovementComponent.class);
        AnimationComponent animation = entity.getComponent(AnimationComponent.class);

        animation.elapsedTime += deltaTime;

        someSpriteBatch.draw(animation.currentFrame, transform.x, transform.y);
    }
}

That being said, in terms of the component definitions you provided, logically the AnimationSystem would only require access to the TransformComponent and the AnimationComponent. If you want to manage entity movement, you could create a MovementSystem which requires access to the TransformComponent and the MovementComponent.

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

Start simple: x and y and are in the Transform component, so read them from here. Same for the sprite: read it from the component where it's stored.

You really don't need to make it more complicated than that.

\$\endgroup\$

You must log in to answer this question.

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