I’ve been using delegates in my code quite a lot, but I’m still not sure how I should bind my delegates. I mean, what are the pros and cons of binding delegate in one way or another.
First of all with all different delegate types. I know the difference between single-cast and multi-cast delegates - single-cast delegate can bind only one function at the time while multi-cast delegate can be bound to multiple functions. But I am not sure where dynamic delegates could prove useful - according to documentation dynamic delegates “can be safely serialized to disk” and according to that documentation link “their functions can be found by name and they are slower than regular delegates”, which is the reason I’m not using them. Where could dynamic delegates be used wisely?
Now about binding delegates in different ways:
When it’s wise to use one way or the other to bind delegates. When to use BindUFunction function to bind delegates? Also when it’s good to to use BindStatic() function (instead of just calling static function) or BindRaw() or BindSP() (doesn’t it neccessarily have to be bound with an object?) . I think I understand BindUObject(), but it would be great to know Your opinion about that way of binding a delegate.
I hope I don’t seem silly right now asking so many questions, but I need clarification as I want to know exactly what I’m doing when I next time declare and bind a delegate. The main documentation link about delegates hasn’t given me much help when and which way I should bind delegates.
Waiting for you response.
As for dynamic vs. non-dynamic delegates, I try to use non dynamic wherever possible. If you need to provide a blueprint interface then you are forced to use dynamic. In some cases I create two delegates, one for each type. This is because non-dynamic delegates can have payload values which is very useful in c++
As far as I understand, the different methods track the function that will be called in different ways. As UObjects can be garbage collected there is a chance that by the time the delegate is executed the object will no longer be valid memory causing a crash. Using BindUFunction or BindUObject ensure that if the object becomes invalid the delegate will not be called for it.
BindSP is similar but uses the unreal shared pointer library to keep track of whether the object is alive or not.
Bind Static and Bind Raw do not keep track of object lifetime, so they are much more dangerous to use. If you are using these it is very important you unbind from the delegate when the object is destroyed otherwise you are leaving a pointer to invalid memory in the delegate.
I hope this is helpful!
To make it clear:
Whenever I want to use delegates in blueprint editor I have to use dynamic delegate, that’s also why they’re slower. When I don’t need to use created delegates in blueprint editor and do it natively in c++, I could use non-dynamic delegates.
As I understand using BindUFunction, BindUObject or BindSP functions to bind delegates are fairly similar then. I still don’t understand the difference between those binding ways.
So BindStatic and BindRaw are rarely used, but do you have any idea whenever those delegates could be used?
By the way, thank you for your explanation. It got alot clearer for me when to use dynamic delegates.
If you have a c++ class that is created using the new / delete operators rather than methods in unreal you will have to use bind raw. This is because unreal cannot track the new and delete operators to work out whether the instance of the class is valid.
Bind static is for static functions, these functions do not belong to an instance of a class so it is always safe to execute. For this reason they only have one parameter to the BindStatic function - the function pointer. There is no need to pass in ‘this’ which is the instance pointer as static functions do not require an instance
But why not call static function instead of binding a delegate to static function? As far as I know, UObject inheriting classes will be garbage collected by game engine and I should not use new or delete operators to deal with memory usage. But delegate binding by using BindRaw method makes sense when the class doesn’t inhert from UObject so you could still use delegates, although it doesn’t make sense why I shouldn’t use sharedpointer based delegate instead as it’s easier to deal with memory usage then (in my opinion).
You can call the static function directly, but that requires you to know what the function is. The delegate enables you to call static functions in a generic way.
Shared pointer and UObjects are two different ways of handling memory, and they are incompatible.If you try to use shared pointer on a UObject the shared pointer may delete the object leaving invalid memory in the garbage collector, and vice versa the garbage collector may delete it leaving invalid memory in the shared pointer. BindSP exists for things such as the Slate UI library, which uses shared pointers rather than UObjects. Really they do the same job, you just need to pick one based on the pointer you have
Awesome! As I plan to use slate UI soon, it will be handy to know that.
Thanks for your time to explain this subject to me.