I think I understand how to use delegates and seem them used a lot. I am trying to understand why I should use them instead of just calling the function on the object? Is it just so you do not need a reference to objects that are “listening” for the delegate?
It’s more about doing a thing in multiple different classes when a thing happens. There is an advantage to not needing a bunch of references, but the main reason is convenience of design.
If you have multiple classes that all need to react to an event, delegates are the best option. Say you have a UI button. If it needs to do multiple things across multiple classes, you could either A) have a reference to each class in the button class and call functions on each or B) have each reactive class and the button reference a multicast delegate in a separate, lighter class. The button calls the delegate and each reactive class binds to it so they all do their own thing when the delegate fires.
Another advantage is for creating a public API. If anyone else may use your code in the future, it’s helpful to expose some events as delegates. The editor does this everywhere. Without the FOnPostEngineInit delegate we wouldn’t know exactly when the Level Editor was loaded and available. We would have to check on a timer interval or edit the source code!
I think of delegates as being the edges of my codebase. If you have a function call, both the class calling the function and the class with the function need to know about each other and have dependance on each other. This dependence is good, where it is necessary. The core classes of my game all have interdependence (character, gamemode, playercontroller, ect). As you branch out, however, and get to the “edges” of your code base (HUD, stat collectors, fxs or cosmetic related object), you don’t want this dependence because it makes your code base more clunky and unwieldly. Now you switch over to delegates and keep everything clean. I put a ton of delegates on all my core classes (some I don’t even have uses for yet), and then later on I can add delegates wherever I want without two way dependence.
Basically: Before you make a function, ask yourself, do both classes absolutely need each other to make sense and work properly? If the answer is no, you can probably use a delegate.
I wouldn’t even be lying if I said delegates probably freed up ~30% of my technical debt.
Calling functions is for when you know exactly what you need to call the function on.
Delegates are for “events” when you don’t know what you will be calling the function on. It leaves it open so any other object can register for some event, without knowing anything about the event originator, and without changing the event originator’s code.
Examples where we use them heavily: “state changes” in stuff like animations, interpolations, or operational states. Extremely convenient when an actor/component can easily register to know when some state change has occurred in some other actor/component.