Hi everyone, I’ve been reworking my UI to use event dispatchers (i was mainly using interfaces before) but I don’t know if I’m doing this correctly.
This is what my main ui widget looks like:
I’ve been always told that casting is terrible and to avoid it at all costs, but I’ve noticed that to use event dispatchers it’s rarely possible to avoid that, so is what I’m doing fine or is there a better way?
Another question I have, weapons in my game call the event dispatchers and the ui responds to them, but that means that the ui has to have a reference to the current weapon, so should i go through the player instead?
And also, for stuff like children wbps talking to their parent, should i get the parent and cast/use an interface, use event dispatchers or in the parent call a function in the child and set the ref that way?
Casting isn’t to be avoided at all costs or it wouldn’t be there in the first place. It just gets misused a lot of the time so novices are told when starting out to avoid using it if at all possible because you can accidentally create cyclical references and bog down memory by keeping everything loaded into the RAM.
Casting to the player’s class is almost ALWAYS free, memory wise, because they’re already loaded nearly all of the time. You can do it without any repercussions.
The problem is doing a lot of casts to cast to things that aren’t already loaded. So if you hit an actor and want to know if it was a certain thing, if it’s something you KNOW would be loaded, like the player, or the ball in a basketball game, go ahead and cast to it. Other stuff like… “Only THIS type of shoe makes this effect happen on collision” then use a “class =” bool check node and a branch, THEN cast, otherwise you end up loading it into memory (whether you need it for gameplay or not) whereas the class check I believe is just an ID comparison.
So yeah Casts are not to be avoided at all costs, just to be avoided when there are other methods. If you NEED a function or event FROM a SPECIFIC class of actor, cast to it.
Oh alright thanks. I mean i was always paranoid about casting because of everyone always says that interfaces should be used instead and that’s what i was always doing. And about the EDs, is it better to have a reload function (the goal is to set the text in the ui) that goes like this: in bp player, player presses a button → weapon bp (passes its ammo variables) → player bp(does the same) → ui wbp, or to use an event dispatcher from the weapon to ui directly?
Casting does add memory weight. I try to avoid it like the plague and use interfaces. Even Controller, Character, Player state communication is handled with BPI’s.
If you have to cast and you’re casting to the same instance a lot, you should create a reference variable. The process of casting has a little overhead. A variable mitigates that repetitive hit.
I haven’t run into many instances where a cast is absolutely required or better. Animation BP access to character class is the only hard ref I agree with.
End of day I feel the weight of interface vs memory weight of cast is the determining factor.
Using interfaces in a complex way requires a lot of thought and organization. That’s the only downside to them on large complex projects. I usually prototype with casts to determine what all is needed, then create the architecture for BPI’s.
Dispatchers require a cast reference. Only time I use them is for “One to Many” communications. Like a switch that manages many lights etc.
Your Inventory manager should be the ruling body for ammo. This is typically in an actor component in the Player State class. Inventory is Data. Manipulation of that data happens in the class in which it is stored.
ALL Character UI should be managed by the Controller class vs in the character.
Weapon fires → BPI to Controller (deduct ammo).
Controller → BPI to Player State → Deduct Ammo.
Player State (Deduct Ammo Event), On change → BPI Controller → Update Ammo (current ammo #)
Controller (Update Ammo Event): calls event in UI (Widget) that sets text.
Controller creates a reference variable for each individually created widget.
e.g. crosshair, inventory etc.
Absolutely no casts needed here. Just organized BPI’s.
You have direct access from Player State to Controller and vice versa without casting.
These are generic references to the base parent class. Interfaces are inherited at the root parent class.
my understanding is interfaces are MORE expensive than casting, assuming as @Mind-Brain said and the class is already loaded.
i do think event dispatchers are better in the example above but what you can do is make an ‘Event Actor component’ and move all your events to that so you can Cast/Bind to a lightweight modular component
Generally speaking it depends on what you are doing. For example with Anim BP there’s so many calls per frame to vars/functions in the character & cmc an interface would be inefficient. So a hard reference is the better call. Down to numbers robust BPI’s are lighter than empty AC’s… typically.
In general the character class shouldn’t need to know anything about any other actor in the game world beyond the controller. And yet the calls you make to the controller are so light that an interface is perfect.
I’ve just setup an interfaced based projectile object pool as an actor component in the character class. My Interaction system is another actor component that’s 100% BPI based. This system will touch every single replicated interactive actor in the game.
Downside to casting is it creates a hard reference. Everything that class references is inherited down the chain.
For example say I have an actor component in my player state ( AC_Inventory ).
If I cast to controller in my character class. And my Controller casts to Player State, then my Character has a hard ref to the controller, Player State and the AC_Inventory.
All references I do store are as generic as they can get.