2
\$\begingroup\$

My components are 100% isolated. No component knows about anything outside of itself in any way. Components have functions that operate on their internal state, and events to inform what's happening to their internal state.

I then create a script on my game object called CommHub where I hook up all the component events to component functions. This works really well and I love it. I love having completely decoupled components and one central place to see how the communications between them are setup. It gives me a high level, while being functional, view of said game object, and some game objects can have a lot of components.

My question is now entity to entity interaction and how to do that while keeping this idea of 100% decoupled components.

Say we have the player game object and a zombie game object. Each is made up of components. The high level idea is the zombie looks in a radius around itself for all entities and if one is the player it'll walk towards it. When in a certain range it'll start a struggle with the player. This is the first interaction between 2 entities. The zombie controller component is the one that checks if it's in range of the player (its target found from the search component) and if so needs to communicate with the player to tell it to start a struggle with this zombie.

A system for communication between the entities is what I'm interested in talking about, while still keeping the rule of components not being aware of other components directly (ie. no component knowledge from within another component). I can't think of a good way to do it like I have with inter-entity components.

How can I approach this?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ What about a singleton "system" defined for each interaction domain? So perhaps a StruggleSystem that has the function Struggle() and event onStruggle. In the comm hub script for the zombie it registers it's StruggleComponent.onStruggle with the StrugglesSystem.Struggle(). Then in the player comm hub it registers the StruggleSystem.onStruggle with it's struggle components function. So the zombie raises it's event which calls StruggleSystem.Struggle() which in turn raises it's onStruggle which is hooked to the players Struggle() component and no the player knows and components are still decoup. \$\endgroup\$
    – user441521
    Mar 2, 2017 at 2:58
  • \$\begingroup\$ I really like your architectural ideas, you could even have the specific CommHubs inherit some interfaces like IHasHealth \$\endgroup\$
    – aeroson
    Apr 26, 2017 at 13:29

1 Answer 1

1
\$\begingroup\$

I would have designed it so that the StruggleComponent holds a reference to the target entity id.

For the zombie, it would determine the target entity id when an unknowingly hostile entity enters the aggressive radius of the zombie. When the AI check detemines an entity has entered that space, it raises an event and sets the target on the StruggleComponent. This causes the zombie to move to the target and start attacking.

The way the player entity is notified of the attacks would be to use that target entity id to dispatch an event to that entity directly, like as follows:

// somewhere in the struggle component's code for attacks
Entity target = getEntity()->getEntitySystem()->findEntityById( targetEntityId );
target.sendEvent( new Attack( 25 ) );

In this case, the zombie used the target entity id to get the entity reference from the entity manager and then send it a direct event of an attack of 25 damage.

Internally, the target entity may likely distribute that event to all its components allowing each component to handle that event as it needs to. The most notable would be that the Health related component would reduce its HP by 25.

\$\endgroup\$
2
  • \$\begingroup\$ It's an interesting idea, but I like event style programming and even though you say send it an event you're really more sending it a message for it to do something with, where an event is more of a subscription, but a subscription requires knowledge of the internal event which couples things. What I ended up doing is having "world" events that entities can hook to. It acts as the 3rd party between entities. \$\endgroup\$
    – user441521
    Apr 20, 2017 at 14:00
  • \$\begingroup\$ It can seem odd because you have a reference to the other entity most times (like when picking or zombie finding the player) but it keeps things unaware of each other and all interaction is an event sub to an action, which can easily now be put into a json file and created visually from some kind of editor, which I like. (I'm using lua for all of this). \$\endgroup\$
    – user441521
    Apr 20, 2017 at 14:03

You must log in to answer this question.

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