Force blueprint function override as function instead of event

I’ve written a function in c++ that takes a struct reference as an input, with the intent to modify values inside the struct.

UFUNCTION(BlueprintImplementableEvent, Category = Buff)
void OnBuffStart(UPARAM(ref) FBuff& oBuff);

The issue is that since the function has no output, attempting to override the function in a blueprint creates an event instead of a function. Using an event for this causes a warning, “No value will be returned by reference. Parameter ‘oBuff’.”

Is there a tag to force a function with no output to be overridden as a blueprint function?

Currently a workaround is to add an output to the c++ declaration, override it in the blueprint as a function, then remove the output parameter.

Good god, yes please. I want to use local variables, so I want my overridden functions to actually be functions. It seems dumb that I have to make an extra function to call into from the overriden event in my BP just so I can have local variables and a clean graph.

Good news - I’ve just added a metadata option to the build we use for GroundBranch to do just this.

	UFUNCTION(Category = "AI|Director", BlueprintNativeEvent, Meta = (ForceAsFunction))
	void SetInitialBehaviour(class AGBAIController* AIController, const TArray<FAIInitialBehaviour>& InitialBehaviours);
	void SetInitialBehaviour_Implementation(class AGBAIController* AIController, const TArray<FAIInitialBehaviour>& InitialBehaviours);

Guess I’ll see about creating PR.

1 Like

Did you ever share that feature anywhere public?

Ha, I put this meta attribute on a function and wondered why it didn’t work. Any chance of PRing this?

I just solved this using Kris’s answer. I just added the && !InFunction->HasMetaData(FName(TEXT(“ForceAsFunction”)) bit and it worked like a charm. This obviously requires source built engine.

bool UEdGraphSchema_K2::FunctionCanBePlacedAsEvent(const UFunction* InFunction)
{
	// First check we are override-able, non-static and non-const
	if (!InFunction || !CanKismetOverrideFunction(InFunction) || InFunction->HasAnyFunctionFlags(FUNC_Static|FUNC_Const))
	{
		return false;
	}

	// Then look to see if we have any output, return, or reference params
	return !HasFunctionAnyOutputParameter(InFunction) && !InFunction->HasMetaData(FName(TEXT("ForceAsFunction")));
}
1 Like