AddDynamic is permanent!

Hello guys,

I’m using UE 4.18.
I find myself in this situation, in a constructor I have:

CapsuleComponent->OnComponentBeginOverlap.AddDynamic(
this, &ABaseCharacter::OnCoverVolumeBeginOverlap);

This is the ONLY place where the function OnCoverVolumeBeginOverlap is added to the delegate OnComponentBeginOverlap. It all works fine until I decided I don’t need this binding. So what did I do? I removed this code from my constructor. Guess what? This thing doesn’t go away. The function OnCoverVolumeBeginOverlap keeps getting called. I cleaned my solution, rebuild it several times, deleted the Binaries, Intermediate folders and it still persists. What is going on? This is driving me crazy. I’m absolutely sure this is the only place that this binding is happening. I tried calling OnComponentBeginOverlap.Clear(), still doesn’t help. Anyone experienced such a thing?

EDIT:
UE4 delegates are serializable. It appears that binding delegates in constructors is not the best approach because they are used by the editor as well. Binding delegates in BeginPlay() or another suitable place seems to eliminate the issues. More info in the comments.

Best regards.

1 Like

Posting here for completion’s sake:

I suspect what is happening is that a blueprint subclass of this class is causing the issue. Some UE4 delegates can be serialized (saved), and when you created the blueprint, the constructor created that delegate binding and serialized it to the saved blueprint asset.

If you change the constructor of a class in C++, there’s no guarantee that those changes will propagate to existing blueprint assets you have created - so you will have to delete and re-create the blueprint from scratch. There isn’t an easy solution to this problem in general, unfortunately.

In this particular case, you might be able to add a ‘Clear’ method to the constructor then open and re-save the blueprint asset.

Hope this helps!

1 Like

Hello TheJamsh, I will give a try ASAP. That’s a very good guess. Will let you know how it goes.

For future readers, indeed the only way to fix it was to recreate the blueprint. I tried using
OnComponentBeginOverlap.RemoveAll(), OnComponentBeginOverlap.RemoveDynamic(), OnComponentBeginOverlap.Clear() in the constructor in question and nothing helped.

Ehi dude, I know that some time has passed and you may have found a better solution, in any case I have found an easy and quick way to fix this problem: my the trick is to remove the bindings to the delegate in the BP “Event Graph”, for example after the Beginplay or some other default or custom event.
For example I have a custom userwidget which I’ve implemented in C++, delegates included. When I create the derived BP for design its widgets, I go to the Event Graph and from the “Pre-Construct” node I remove all the bindings to my delegate. This works fine and you don’t need to delete and recreate the BP every time !

Cheers!

Hello evethir!

Thanks for taking your time giving a tip. Your solution is reasonable! Good job coming up with it. I remember this problem. I was really frustrated with it but I can see why it ends behaving like that. It does make sense to act the way it does. I came up with a workflow that eliminates this kind of issues. I bind my delegates in events like BeginPlay or something else and I avoid binding in the constructors since the editor uses them as well and things can go wrong. So far I can’t see any disadvantages to this “new” workflow.

Happy New Year!

4.21.2 still has this problem, and this solution does solve the problem but only temporary. once you remove the Unbind All Events From X node the problem will return.

in my situation it is a problem with an actor component, removing the component and adding it again solves the problem sadly.

Hello marineuac,
I still don’t have a deep understanding of what is happening behind the scenes, but the general idea is that the UE4 delegates are serializable. Binding delegates in a constructor seems like it’s not the best thing to do since the constructor is used by the editor too like I mentioned previously. So I have been binding my delegates in BeginPlay or another suitable place. Perhaps you can share more details about your case?

There is a solution actually, and it’s simply renaming the UPROPERTY pointer to the object/component you are binding to. I’ve also renamed the internal name of the object at the same time, but I don’t think that is necessary.
After renaming, recompile and save all the BPs that derive from that actor, then rename it back (and optionally re-save the BPs again). It will now work. Though, given this problem, binding stuff in the constructor might not be the best idea, but it is tempting as you have access to the event in the editor previews and also just before begin play and stuff (plus you don’t really need to worry about end play or the actor being in a hidden level and receiving a temporary end play).