Using Multicast Delegates with BlueprintImplementableEvent

I’m “cross-posting” this from AnswerHub, in hopes that more experienced people view and can help me solve this issue:…mplementa.html


I’m having trouble hooking up a Multicast Delegate to a BlueprintImplementableEvent function, for a simple health/armor display. I’m doing it in C++ for maintainability purposes :slight_smile:

Here’s the code I have:

On my character header:

    DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHealthChanged, float, Health, float, Armor);

    FOnHealthChanged OnHealthChanged;

(I’m not sure if BlueprintAssignable is needed there, since I"m trying to assign it using C++, even though it will execute blueprint code. Left it in anyway. Advice is welcome :slight_smile: )

At the end of my TakeDamage function, on my character:

    OnHealthChanged.Broadcast(Health, Armor);

And on my custom UUserWidget, I declare on my header:

    void HealthChanged(float Health, float Armor);

And on CPP:

bool UHavenBaseHealthArmorWidget::Initialize() {
    bool Success = Super::Initialize();
    if (!Success)    return false;

    // There are sanity checks in here, making sure all pointers are fine.

    MyCharacter->OnHealthChanged.AddDynamic(this, &UBaseHealthArmorWidget::HealthChanged);

    return true;

But when I damage myself, nothing happens. If I set a breakpoint tin the blueprint, it seems it’s not executed. If I set a breakpoint on my character TakeDamage function, the function is being called.

I’m not sure what I"m missing there to make it work. Any idea of what’s wrong and how I should fix it?

Thank you very much in advance!

Okay, so this issue is driving me nuts…

I’m more than 4 hours straight with this, and I can’t find a solution. One of those cases you seem to be almost there, but can’t find what’s wrong! :frowning:

So, if I do:

MyCharacter->OnHealthChanged.AddDynamic(this, &UBaseHealthArmorWidget::HealthChanged);
MyCharacter->OnHealthChanged.Broadcast(MyCharacter->Health, MyCharacter->Armor);

it works!

With debugging, I noticed that [FONT=courier new]OnHealthChanged has a [FONT=courier new]InvocationList array inside it.
At that moment, there’s a single element in it.

After I call the broadcast in my player character object (Be it in [FONT=courier new]TakeDamage() or anywhere else I tried), this [FONT=courier new]InvocationList is empty!

I do have the engine symbols to debug with, but the delegate code is hard to navigate (too many macros, etc.), I can’t find out where that’s being removed.

Someone told me to check for network data, but it’s running on the Editor, no network yet (I usually do everything locally, and only after it’s working I bother with supporting network).

I’m out of ideas on what to do, and I can’t find anything about it on web. Was anyone successful on binding a [FONT=courier new]UUserWidget function to an [FONT=courier new]ACharacter multicast delegate?

Did I miss something in there?

Thank you very much, again, in advance.

Do you have severe framerate problems that you want to reduce by using events? Otherwise just poll the armor and health from the character inside the Widget. Bind a widget getter and read the variable from there. This is the way we do it and so far we can’t see any framerate issues.

Hello FrostyElkArne,

Thank you for your input!
While I’d generally agree with that, I’m pretty much trying the “basic scenario” for hooking up a widget function with a multicast delegate.
Sure, a simple thing as getting the health value from the character won’t be a big performance hit, but there are other areas of the UI that will need more cpu intensive logic. For those cases, I’ll definitely need a better system than polling every frame.

So, in hopes of learning this, I’m attempting to do this hook.

Sadly, I’m starting to thing I hit a bug. I can’t find the reason why the Invocation List gets emptied in there :frowning:

I’m still hopeful someone out there knows the answer to this issue :slight_smile:

Thank you, again!

Okay, solved the problem.
The problem is that everything I was doing was correct, but the multi-cast registering needs to be done every time the character respawns and, due to a different spawning setup on my game, it was being respawned right after the widget was being created.

Just re-registering on the delegate after the spawn solved the issue! :smiley:

Hope this helps someone out there struggling with the same problem :slight_smile:

Would be awesome if Unreal had a “Script Execution Order” mechanism.

I often use this workaround to avoid issues like that:

That is a “hacky” example of how to control the order each Blueprint in the map calls their “Begin Play” events.