Blueprintable delegates with return values

Is it possible to declare delegates with return values that can be assigned in Blueprint?

I know you can have input only events with BlueprintAssignable, but as far as I know the delegates have to be multicast and thus can’t return anything.

For some context: I have a base class of type Item. Items have different levels, and have different stats depending on the level. For example, item level 1 may give +10 damage, item level 2 may give +20 damage. The scaling is calculated in a function on the specific item subclass which takes the level as a parameter and outputs a float, like “float calculateDamageBonus(int32 itemLevel)” only it’s in Blueprint. The items have descriptions generated from the stats that they give. It’s pretty easy for an item to format a string to describe the stats it gives at a certain level. However I want to describe upgrading between these levels, eg. at level 1 the item says “Gives +10 damage” but when given the option to upgrade from level 1 to 2, I want to be able to generate “Gives +[10 → 20] damage” so that the player can see which stats are being upgraded by how much.

I want Item subclasses to be able to call a helper function somewhere that takes a delegate (which refers to the stat calculator function on the item that takes an integer param and returns a float) as a parameter, and returns a string.
The helper function calls the delegate multiple times with different integers for different levels, and formats the resulting float values into a string such as “[10 → 20]” and returns that.

Bump. Did you discover anything? I’m guessing it’s not possible, but that seems like a rather large and unexpected limitation. Or is there a workaround that I’m not seeing?

Nope, haven’t found or heard anything about this unfortunately.

Yep, that’s a pity. Would be nice to know if there are any plans to add this functionality to Blueprints. Thanks for updating, anyway.

Thanks, but the issue is working with such a delegate in Blueprint, not C++. Only dynamic delegates can be exposed to Blueprint. Further, even though non-multicast dynamic delegates can be exposed, there is no obvious way to assign a function to one in BP when the delegate has a return value.

Have you tried something like this:

DECLARE_DELEGATE_RetVal_OneParam(int32, FMyEventDelegate, bool);

/* The UPROPERTY is experimental and not tested */
UPROPERTY(BlueprintAssignable)
FMyEventDelegate OnMyEvent;

int32 GetMyEventResult(bool EventConditional) const
{
	if(OnMyEvent.IsBound())
	{
		return OnMyEvent.Execute(EventConditional);
	}

	return 0;
}

Take a look at Engine\Source\Runtime\Core\Public\Delegates\DelegateCombinations_Variadics.h

There is pretty much every possible delegate type you might ever need.

If that does not give you a blueprintable Delegate, you can still declare GetMyEventResult() as UFUNCTION that is BlueprintCallable

Edit: Just realized you wanted a blueprintable Delegate.

1 Like

Ah if that is what you want, why not use an Interface with BlueprintImplementableEvent?

The Reference& parameters will be converted to return values.

How can I pass the function by delegate to another function which can call it? Added to description for context.

I still don’t believe it is possible to use delegates like this in BP unfortunately, but from what you describe it doesn’t sound to me like you need delegates in this case.

You could make CalculateDamageBonus a BlueprintImplementableEvent. Then your BP item subclasses would implement the override rather than declaring a new function. You can then have a function in your item base class such as FormatUpgrade(int32 FromLevel, int32 ToLevel) which just calls CalculateDamageBonus for each level and does the formatting. Wouldn’t that achieve what you want?

Following up on this, using an output parameter worked.

I use c++ to declare the delegate and a static formatting function which takes the delegate.

DECLARE_DYNAMIC_DELEGATE_TwoParams(FItemCalculatorDelegate, uint8, stack, float&, output);

// Uses the given item value calculator function to format scaling values for a description
UFUNCTION(BlueprintPure, Category = "Item")
static FText formatScalingValue(FItemCalculatorDelegate valueCalculator, uint8 stack = 1, uint8 upgradeCount = 0, float multiplier = 100, int32 maxFractionalDigits = 1);

In BP I define a function with the same signature as the delegate:

http://i.imgur.com/PYPk2HF.png

Then elsewhere in BP I can specify that function using the Create Event node and pass it as a parameter into the formatting function defined in C++.

http://i.imgur.com/nmqtbgv.png

1 Like

Acren you saved my life!

I know this is pretty late but it seems like this problem still exists. In my answer, I would like to show a more concrete version of Acrens comment where you can also pass blueprint functions via lambda to external libraries.

I have a color library where you can store custom gamma functions inside std::functions. My goal was to store Blueprint functions there as well:

Declare the delegate:

DECLARE_DYNAMIC_DELEGATE_TwoParams(FGammaFunctionDelegate, float, InputValue, float&, OutputValue);

Save the delegate in a variable inside a UCLASS:

FGammaFunctionDelegate gamma_delegate;

Define a BlueprintCallable function that takes the delegate as a parameter:

UFUNCTION(BlueprintCallable, meta = (DisplayName = "Create Gamma Function"))
		static UGammaFunctionPart* CreateGammaFunctionPart(FGammaFunctionDelegate Function, float UpperBorder);

Inside this function create a lambda which executes the delegate (and pass the lambda to a object of the external library):

gamma_delegate = Function;
gamma_function = new color_space::gamma_part([this](float Input)
{
	float result;
	gamma_delegate.ExecuteIfBound(Input, result);
	return result;
}, UpperBorder);

Now unreal somehow knows that the return value of a blueprint function has to be assigned to the reference parameter…

A sample gamma blueprint function might look like this:

And this way you can assign the blueprint function:

283470-createevent.png

Now each time the external library tries to do a gamma correction it will execute the std::function which stores a lambda. The lambda will call the delegate which finally executes the blueprint function. The return value will be passed down to the point where the std::function was called.

4 Likes

For future reference you can replace most of your solution with this (at least you can in UE5.4):

UPROPERTY(BlueprintReadWrite)
FGammaFunctionDelegate gamma_delegate;