Download

Is it a good idea to use event for everything?

So i’m thinking of ditching inheritance in favor of composition, and currently my components are quite tightly coupled with one another. For example i have an Inventory Component that is tightly coupled with my loot component, item component with attributes component and so on. So i had an idea to decouple those components using an observer like pattern. Basically if one component wants to connect with another, it simply only needs to dispatch an event to my event manager class, and the other component will only listen. This way each component doesn’t need to know about another component and i don’t need to do a bunch of checks to see whether an actor has a component or not. So in the end, every actor that wants to use my components needs to have its own Event Manager & every single action that an actor makes is driven by events.

Is this a good idea or not? Cause i’m having some doubts and feel kinda scared of having to rewrite everything again.

maybe this isn’t applicable to your situation but when I have 2 tightly related classes I usually try to merge them into a single class, especially if they share a lot of dependencies or have a circular dependency on each other.

i’m just speaking from a general programming perspective here because i just got started with the engine, but…
why shouldn’t looting be just a function of the inventory? it’s the process of putting things into itself.
items intrinsically have attributes, it should be part of the item class shouldn’t it?

why shouldn’t looting be just a function of the inventory? it’s the process of putting things into itself.

Well in my game it’s really a different thing, an actor with a bunch of items in their inventory like potion, tools and so on won’t necesarrily drop the same loot as their inventory content. It’s an entirely different database of things & concerns. For example, if i want to add a dead body actor that is lootable, i wouldn’t need them to have a bunch of functions to handles its inventory (so, no inventory component), i only need what loot they have + other data that would generate the loot.

items intrinsically have attributes, it should be part of the item class shouldn’t it?

eh sorry by attributes i mean, my rpg character attributes. item attribute is indeed included in the class, but, if an actor has a component that allows itself to use an item. It doesn’t matter if they have an rpg attribute system or not, but if they do, add the effects of the item on the character attributes (by using events to the observers). So for example if i want to populate a certain place with a lot of actors and they’re not capable of combat, yet they can interact with items like maybe drinking something or whatever, i can show the animation and visual effects and all, but i don’t do anything else because they’re not supposed to have an attribute.

Using delegates and event binding brings no disadvantages. I use in in many different places.

It makes absolute sence to build small class in a modular component based fashion because you can split up the logic and your source code is mich easier to support later on and reusable.

Delegates/ events are executed like normal method calls. The only “problem” is that it is not defined which event handlers are executed in which order.

When you have several handlers in some cases handler A might be the first or the last one which is executed.

It makes absolute sence to build small class in a modular component based fashion because you can split up the logic and your source code is mich easier to support later on and reusable.

yup, i agree with this

Delegates/ events are executed like normal method calls. The only “problem” is that it is not defined which event handlers are executed in which order.

Ah i see, i didn’t know about this. So this is basically for multicast delegates right? I don’t think i have a need for an ordered handling of events since every component have different concerns. So it doesn’t matter which one starts first. But i’ll take a mental note of that thanks!

Right.

It is like the engine holds a list of “handlers which want to be informed”. When the delegate is broadcasting it basically calls there handling methods in “some undefined” order. :slight_smile:

1 Like

Going through a general purpose event bus is flexible, BUT it’s also an absolute pain to debug, because all the event sources and sinks get anonymized. You can no longer use the debugger to step through a full chain of cause and effect. I would recommend against it unless you absolutely need that level of decoupling (such as, for example, networking sending events across machines.)

In general, when you have things talking about other things, they’re either legitimate sub-objects of the thing (owned and managed by the owner thing,) in which case it’s totally legitimate to have close coupling (specific classes,) or they are use in a cohesive way, in which case an interface is generally the right way to couple them. The interface is defined by whomever needs to use it, and everyone who wants to be used that way, implements that interface.

Example of close coupling: A physics engine needs internal details of rigid bodies and collision shapes, both because the necessary math requires precise two-way dispatch, AND for performance. Thus, those objects are generally closely coupled.
Another example of close coupling: A particle system needs coordination between its emitters, both for the necessary math, and for performance. Thus, those objects are generally closely coupled.

Example of loose coupling: A variety of things might want to be interactable in the world. Thus, there’s likely an “interactable” interface, that tells the player controller and its UI where it is, and what the available interactions are, as well as some function to actually do the interaction.
Another example of loose coupling: A variety of things will want to be managed by an inventory, equipped, and/or dropped in the world. Thus, there’s likely an interface that tells the player controller and its UI what the item is called, what it looks like, how big it is, and has functions to instantiate an Actor for the object for using in the world.

1 Like

Personally, I use events quite a bit.
I’m aware that DYNAMIC events have some cost to them due to them being serialised for Blueprint reasons, but other than that I don’t think there are any other real costs.

I don’t really like the EventManager approach. In some situations it works but I like everything having its own purpose - not all shared together.

What I tend to do is my Components will have events/delegates and the Actor which owns those Components will subscribe to those events. This approach makes it really easy to add functionality using BP.
For example, I would have a WeaponsComponent which is responsible for everything to do with managing Weapons. The Character will simply subscribe to the relevant events, such as ‘OnCurrentWeaponChanged’, ‘OnWeaponAdded’, etc, to do the things it needs to do, i.e. attach to sockets, update HUD, etc.

My remedy for the Component checking that it seems like you’re talking about is using UInterfaces (especially useful in Blueprints).

Yeah i knew something like this might happen. My main issue with interfaces is i probably need to redefine a bunch of interface functions in each actors, hmm i really need to rethink this through again.