How to access a BlueprintImplementableEvent in Level Blueprint?

I have a pickup class, with several custom events, among them:

	UFUNCTION(BlueprintImplementableEvent, Category=Pickup)
	void OnPickedUpEvent();

	UFUNCTION(BlueprintImplementableEvent, Category=Pickup)
	void OnRespawnEvent();

This event shows up on any class blueprint that uses this C++ class, but it doesn’t shows up on the level blueprint.

Any ideas?

I’m trying to make some lights in the level change color when a pickup respawns or is picked up.

#Custom Level Blueprint

Make a custom level blueprint so you can teach your level BP and your items to communicate in the C++ directly

or also then you can write BlueprintImplementable events in the Level BP that the items call in the C++ and you implement in the Level BP!

#Solus Wiki Tutorial on Custom Level BP

#Get Level BP

AYourLevelScriptActor* MyLvlBP = Cast<AYourLevelScriptActor>(GetWorld()->GetLevelScriptActor());
 
if(!MyLvlBP) return;
MyLvlBP->Yay!();

Enjoy!

Rama

PS: remember to reparent your existing level BPs, and do the config thing so all levels use your custom Level BP

Cool, I didn’t know you could extend the level blueprint. This will probably be useful for other situations as well!

Though I wish you could just bind events directly from the object in question, without the need of creating new BlueprintImplementableEvents in the Level BP.

Thanks Rama!

Hi Ixiguis, BlueprintImplementableEvent is a bit of a poor name. BlueprintImplementableEvent means that the function can be overridden in the blueprint, similar to how you can override a virtual function when you inherit a class in C++.

What you want is to define a multicast delegate property, first you need to define the delegate’s type, you can define this just at the top of the header, take a look at some examples in the codebase.

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMyBindableEvent);

Next you just declare a new property of that type on your C++ class,

/** Called when something awesome happens */
UPROPERTY(BlueprintAssignable)
FMyBindableEvent OnAwesomeness;

Then when the event needs to fire, you’ll just call OnAwesomeness.Broadcast(); in C++, to notify everyone listening that the event occurred.

Usually you’ll define both the overridable function and the event delegate for outside listeners.

Cheers,
Nick

Hi Nick,

This seems to be what I’m looking for.

I have succresfully created the delegates and they are being called (Broadcast()) when appropriate. However I am not figuring out how to listen for their events in the level blueprint. Could you give me directions?

Dear Nick,

Why would I ever prefer a muticast delegate to using a blueprint implementable event? In the case that I’ve seen, the same class that has the property and the signature is also doing the broadcasting.

Can you do the broadcast in one class, and other classes have the .h but dont also do broadcasting?

So the event is cross-class and each BP is implementing their response to the event occurring?

And my biggest confusion, it looks like you still need to extend the level BP to give it the ability to listen for the broadcast.

So how is it not better to just use a Blueprint Implementable event?

Ixiguis, Picture for you

#C++ Signature

//Item Highlighted Delegate for use in BP
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(
	FBindableEvent_ItemHighlighted, 
	
	ASolusItemStaticMesh*, 
	TheHighlightedItem,
	
	FVector,
	ItemWorldLocation,
	
	float,
	HighlightBracketDrawScale
);

UCLASS()…

//Bindable Event, Item Highlighted (see delegate declaration at top)
UPROPERTY(BlueprintAssignable, Category="Solus Inventory Delegate Test")
FBindableEvent_ItemHighlighted OnItemHighlighted;

Ixiguis - just follow Rama’s image, that’s the way to do it :slight_smile:

Rama - The reason for defining both and to differentiate is that it’s a difference in purpose. If it’s a multicast delegate, that’s like saying, “Hey - This happened.”. Creating an implementable event lets you take control, “Hey - The user is attempting to jump…maybe you want to do something about it?”.

If there’s no need to let the downstream users take control, maybe you just keep it as a multicast delegate. But if you think the blueprint author may want to redefine behavior, it’s probably worth defining an implementable event as well.

Just a personal preference of mine :slight_smile:

Cheers,
Nick

thanks for the help Nick!

But I still dont get it, the outside listener part!

#What I did

I put the main definition in the .h and the broadcast in the .cpp of my Player controller.

I then defined the BP version as my picture shows.

This runs great cause I’m broadcasting in same .cpp that has the .h definition.

Buut

then I add the .h requirements to my custom level BP

and added the BP implementation of the event similar to picture above

annnnd

the Level BP version is not being called when the Player controller version gets broadcasted!

Is this normal?

This is my attempt an outside listener / a different class listening in on the event

#C++ of the Level BP

just this, no broadcast in the cpp:

//CROSS-CLASS EVENT
//Bindable Event, Item Highlighted (see delegate declaration in PC .h)
UPROPERTY(BlueprintAssignable, Category="Solus Inventory Delegate Test")
FBindableEvent_ItemHighlighted OnItemHighlighted;

#Summary

I thought the point here was to have cross class many different entities listening in on event that occurs only in 1 .cpp file.

But for me the level BP is not getting the signal

thanks!

Rama

PS: really want to understand the reason for delegates over using a low level c++ interface and then just having each class that uses the interface call their own blueprint implementable event in response.

So level designers define the behavior, but the “broadcast” is done via interface casting using ObjectIterator or ActorIterator in the C++

All of this to create a Global Broadcast that each class handles differently, with different BP implementations

Hmm - doesn’t seem normal.

The reason for the difference is to change the behavior. For example, maybe your highlight shouldn’t appear in certain situations - that you want to leave up to the level designer to choose. So you created an implementable event that in a blueprint is able to return true or false if the highlight should be allowed. Which is then used to determine if the broadcasting delegate and actual highlight rendering code should be invoked.

Hmmm, looking at your picture, I assume there should be an Event Dispatcher on the My Blueprint tab? Which you then drag to the Level BP to bind and create event.

Well, I created the delegate, but it’s not showing up on the My Blueprint tab (for the Level BP or any class BP).

Did I miss something?

This is my delegate declaration (ShooterPickup.h):

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBindableEvent_PickupPickedup, AShooterPickup*, Pickup);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBindableEvent_PickupRespawned, AShooterPickup*, Pickup);

Inside the class, under protected:

	/** Called when pickup is picked up */
	UPROPERTY(BlueprintAssignable, Category=Pickup)
	FBindableEvent_PickupPickedup OnPickupPickedupDelegate;
	
	/** Called when pickup respawns */
	UPROPERTY(BlueprintAssignable, Category=Pickup)
	FBindableEvent_PickupRespawned OnPickupRespawnedDelegate;

Also – if I right-click the graph and type “pickup” without “Context Sensitive”, the event dispatchers do show up, but if I click on either one, nothing happens.

5564-untitled.png

Hey Ixiguis, the same thing happens to me, it appears to be a bug. You can work around it I think by getting a reference to self node (or the ShooterPickup object) and dragging a pin off of that onto the background of the bp graph. Then you can select Assign . Does that work for you?

Yes, that works. Thanks!

Thinking about it now, actually it’s a not bug. You need to tell which object will listen for those delegate events. I got confused because Rama’s screenshot doesn’t connects anything on the Target pin, but I guess that’s because his delegate was declared in the LevelScriptActor (so it is inherited by the level blueprint, unlike my ShooterPickup).

Anyway, for reference, this is how I did it to listen for events on the PickupPowerup_DoomKick only:

Encountered the same problem, my solution was easier than I though (no deal with multicast at all) :

I omitted BlueprintCallable tag in UFUNCTION declaration. Fixed it like this :

 UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category=Pickup)
void OnPickedUpEvent();

Now as soon as you have your object/actor reference, you can call the event from any blueprint as any event/function! :slight_smile: