Interface Event only executed once

Reproduction

Edit: Sorry I didn’t test that before posting, but I can not reproduce the issue in a clean project. However the issue still persists for my project and I am so far unable to fix it.

  1. Declare Blueprintable Interface in C++
  2. Implement Interface Event in a Widget Blueprint
  3. In C++ Call the Interface Function on the Blueprint

Result

The Event in the Blueprint is only called once. The second time, the Interface function is executed, the Blueprint Event is not called.

Example Code

Interface.h

UINTERFACE(Blueprintable)
class ROBOTDEFENSECPP_API UInputModeInterface : public UInterface
{
	GENERATED_UINTERFACE_BODY()
};

class IInputModeInterface
{
	GENERATED_IINTERFACE_BODY()

public:
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "InputModeInterface")
	void SetInputModeForClass();
};

Here I am calling the Interface Function

if (MenuUserWidget->GetClass()->ImplementsInterface(UInputModeInterface::StaticClass()))
{
	IInputModeInterface::Execute_SetInputModeForClass(MenuUserWidget);
	UE_LOG(LogTemp, Warning, TEXT("InputModeInterface is implemented"));
}

Here I am implementing the Interface in my Widget Blueprint

97336-blueprintinterface.png

The first time the Interface Function is called, I receive both the UE_LOG and the PrintString. The second time, I receive just the UE_LOG and not the PrintString. Therefore my code is clearly working, but only the first time it is executed.

Edit 2: I have tried pretty much anything to get it working: I tried rebuilding/resetting the project. I tried it in a clean project (where it worked just fine, but there is virtually no difference how the Interface is implemented. It also worked in the same project with a Pawn Class, but it didn’t work with a different Blueprint Widget. And it didn’t work with recreating the Interface class. I really can’t think of anything else I could try to get it working. So I really appreciate any suggestions to get it working. Thanks everyone.

Hey Jonas,

Try

if(MenuUserWidget->Implements<UInputModeInterface>())
{
    IInputModeInterface::Execute_SetInputModeForClass(MenuUserWidget);
}

I don’t know if there is a difference but in my case this works fine.

EDIT:
Sorry I thaught that your UE_LOG inside the If Statement is not printing.
Just Mixed it up :stuck_out_tongue:

Thank you for your suggestion and sorry for not being very clear about the UE_LOG inside the If Statement. I edited my post to clear that up.

I tried your suggestion anyways, but unfortunately it didn’t change anything.

Hey -

I know you said you were unable to reproduce this in a new project, but could you elaborate on your list of setup steps to help me investigate this issue on my end? Can you provide the full class (.h and .cpp) for your interface as well as explain where you’re calling the interface function from (where the if statement is located)? As a BlueprintNativeEvent, does the SetInputModeForClass have any default code functionality and if so is that being triggered with multiple calls? If there is no default functionality, do you get multiple calls if you make it a BlueprintImplementableEvent instead?

Hey

Thank you for investigating the issue.

For the Interface I created an empty C++ class with the class wizard:

InputModeInterface.h

// Copyright Jonas Jebing 2016

#pragma once

#include "InputModeInterface.generated.h"

/**
 * 
 */
UINTERFACE(Blueprintable)
class ROBOTDEFENSECPP_API UInputModeInterface : public UInterface
{
	GENERATED_UINTERFACE_BODY()
};

class IInputModeInterface
{
	GENERATED_IINTERFACE_BODY()

public:
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "InputModeInterface")
	void SetInputModeForClass();

	// TODO possibly implement void RemoveHUDForClass(); [...]
};

InputModeInterface.cpp

// Copyright Jonas Jebing 2016

#include "RobotDefenseCPP.h"
#include "InputModeInterface.h"

UInputModeInterface::UInputModeInterface(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
}

Concerning the default functionality, I don’t know what that means, so I guess there is none? I am not familiar with BlueprintNativeEvent. I basically copied that from the documentation for Interfaces. BlueprintImplementableEvent behaves exactly the same.

About the if statement:

if (MenuUserWidget->GetClass()->ImplementsInterface(UInputModeInterface::StaticClass()))
		{
			IInputModeInterface::Execute_SetInputModeForClass(MenuUserWidget);
			UE_LOG(LogTemp, Warning, TEXT("InputModeInterface is implemented"));
		}

That is located inside a function called ShowMenu(FKey Key) on my BasePlayerController class and is bound to an input action like so:

void ABasePlayerController::SetupInputComponent()
{
	Super::SetupInputComponent();

	InputComponent->BindAction("Menu", IE_Pressed, this, &ABasePlayerController::ShowMenu);
}

In an attempt to recreate your setup/blueprint, when I add a call to SetInputModeForClass inside my widget bluerpint, I’m only able to add the blue function call node. Can you explain how you get the red event node shown in your screenshot?

I added the Interface to the Widget Blueprint, compiled and then I am able to add the red event node.

I am still only able to get the blue “execution chain” node rather than the red event node. If possible, could you send a sample project or a copy of your current project with the blueprint interface event only firing once for me to test directly?

Yeah sure, but I do not want to share my project publicly and I do not see a way to send you a personal message here. Could you give me your email or any other way to send you a download link privately?

If you’re unable to create the issue in a sample project, You can send me a private message on the forums with a download link to your project.

Sorry it took so long to reply. Unfortunately I am still unable to create the issue in a sample project. So I sent you a download link to my project.

Please let me know if you have any other questions. And again thank you for investigating the issue.

I am not sure if this helps, but I found out that if I comment out lines 31-49 in the Player/BasePlayerController.cpp in the project I sent you, so that the UserWidget is added to the PlayerScreen instead of to the WidgetComponent, the Interface function works as expected.

Please let me know if you have any questions regarding the project.

Edit: With the VS debugger I noticed that the reason the Interface Function is not called the second time around is because the UUserWidget is pending kill (in ScriptCore.cpp [line: 1077]). I have the UUserWidget stored in my GameInstance like so:

UPROPERTY()
	TMap<int32, UUserWidget*> ControllerIDsMenuWidgets;

so I tried storing it on the player controller without the TMap:

UPROPERTY(BlueprintReadOnly)
		UUserWidget* MenuUserWidget = nullptr;

but that did not change anything.

Maybe someone else has an idea, why the UserWidget is marked as pending kill?

Edit 2: Acually I am not 100% sure, because it is my first time using the VS debugger, but the VS debugger just skips to the end of the UObject::ProcessEvent function after it hits the if statement of the following code inside that function:

// Reject.
if (IsPendingKill())
{
    return;
}

I found the problem and a solution: I am displaying the UserWidget with a WidgetComponent. The first time I am displaying the UserWidget, I am calling

WidgetComponent->SetWidget(UserWidget);

and that works as expected. But I am not performing the check

if (WidgetComponent->GetUserWidgetObject() != UserWidget)
{
    WidgetComponent->SetWidget(UserWidget);
}

So I was calling SetWidget every time, even if it isn’t needed. The problem is, that UWidgetComponent::SetWidget() calls MarkPendingKill() on the previous widget, without checking if the new widget is the same as the previous widget. So if the new widget is the same as the previous widget, SetWidget() essentially calls MarkPendingKill() on the new widget. (WidgetComponent.cpp [line: 994])

In my case this lead to the Interface call failing in UObject::ProcessEvent()
(ScriptCore.cpp [line: 1076])

// Reject.
	if (IsPendingKill())
	{
		return;
	}

I would post this as an answer, but I think Epic should take a look and decide whether they want to fix the WidgetComponent::SetWidget() method.

Hey -

I’m glad you were able to find a solution for the issue. I have entered the bug report UE-33782 to investigate the behavior of the SetWidget() function.

Cheers

Just in case anyone in the future is wondering:

The problem is, that UWidgetComponent::SetWidget() marks its previous widget as pending kill. If SetWidget() is called and the incoming widget pointer as well as the current widget pointer both point to the same widget, that widget is marked as pending kill.

This can be avoided by checking if the current widget and the incoming widget are the same.

if (WidgetComponent->GetUserWidgetObject() != UserWidget)
{
    WidgetComponent->SetWidget(UserWidget);
}