How to communicate between different Blueprint components.

Hi, I’ve recently tried to implement a very basic character movement system. Basically just a cube that can move around on the plane, jump, fall down and collide with the ground.

In the spirit of “composition over inheritance”, I implemented the movement in a custom MovementComponent. It moves the pawn around (using the Movement Input Vector as input), jumping works and gravity works as well. The problem: When the pawn collides with the ground, the falling should stop. This requires communication between the movement component and the collision component.

As far as I can tell, it is not possible for a component to subscribe to the event of another component. It is technically possible to call a function or read the state of another component, but this is probably unwise, since you can’t assume that the other component exists in the first place (since components can be removed at runtime).

My solution would be to handle the communication between components in the event graph of the actor: Collision Component triggers event → Actor notifies movement component about that collision and passes parameters → Movement component does its thing.

This results in code duplication though: If I for example have 10 different actors which all use that movement system (e.g. 10 different enemy types), I would have to implement the (rather simple, but still) event graph 10 times. Inheritance can’t solve that problem, since the event graph is not inherited.

How do you solve this problem? Google brought up something about event dispatchers, but I can’t see how they’re supposed to help.

Possible:

  • above, every time the Camera Boom comp becomes Activated, the Character Movement comp will fire a function / event. You’ll need an event with a matching signature or a function that does not return value, so a glorified event.

You can also have components reach out to their owners (or other entities) and subscribe dynamically:

  • the health of this character is handled by an actor component - the AC_HealthManager. And we step into poison (don’t ask, not based on true events):

  • this adds another component which starts talking to our Health Manager:

The underlaying actor is not really aware of any of this. The components talk to each other behind its back.


Inheritance can’t solve that problem, since the event graph is not inherited.

It actually solves everything. What you call not inheriting graph is the the way do go. Instead of duplicating script, one will:

  • above, inherited component overriding

No need to duplicate what’s in the parent.

Inheritance makes it often hard, especially if you want to exchange components later on.

Another approacg is to wirk with interfaces which return a type of component and this is implemented by your character.

Example:
Character A has a MovementComponent M1 and a CollisionComponent C1
Character B has M2 and C2

Both characters implement interfaces to return the superclasses of the components which have specific methods and delegates/bindings.

Than you can call GetCollisionComponent on your character which retrieves the correct component and bind to it from the other component.

Wow, thanks for the amazing replies on this. I combined your ideas and came up with the following solution (of course this is not a proper movement component, just a sketch):


(Event Graph of my movement component)

The Pawn implements the Collidable Interface, otherwise there’s absolutely no code inside the pawns event graph. This is exactly what I wanted.

2 Likes