x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

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

    he 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

Blueprint Interface

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.

Product Version: UE 4.12
Tags:
more ▼

asked Jul 06 '16 at 01:21 PM in Bug Reports

avatar image

AllJonasNeeds
249 26 36 71

avatar image Doug E ♦♦ STAFF Jul 07 '16 at 02:20 PM

Hey AllJonasNeeds-

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?

avatar image AllJonasNeeds Jul 07 '16 at 02:42 PM

Hey Doug

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);
 }



avatar image Doug E ♦♦ STAFF Jul 07 '16 at 06:32 PM

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?

avatar image AllJonasNeeds Jul 07 '16 at 06:34 PM

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

avatar image Doug E ♦♦ STAFF Jul 12 '16 at 02:57 PM

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?

avatar image AllJonasNeeds Jul 13 '16 at 06:55 AM

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?

avatar image Doug E ♦♦ STAFF Jul 13 '16 at 02:36 PM

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.

avatar image AllJonasNeeds Jul 19 '16 at 12:33 PM

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.

avatar image AllJonasNeeds Jul 24 '16 at 11:00 AM

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;
 }

avatar image AllJonasNeeds Jul 25 '16 at 08:11 AM

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.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

2 answers: sort voted first

Hey AllJonasNeeds-

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

Doug Wilson

more ▼

answered Jul 26 '16 at 03:50 PM

avatar image AllJonasNeeds Jul 26 '16 at 07:17 PM

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);
 }
(comments are locked)
10|2000 characters needed characters left
Viewable by all users

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 :P

more ▼

answered Jul 06 '16 at 01:36 PM

avatar image

Cloudy McStrife
465 13 16 38

avatar image AllJonasNeeds Jul 06 '16 at 04:57 PM

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.

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question