Enhanced Input with UserWidget in UE 5.7

Hello there

I would need some help regarding Enhanced Input in UserWidget :upside_down_face:

I need to handle some inputs via Enhanced Input in my UI (UserWidget), but by upgrading my project to the latest Unreal Engine 5.7, a change has been done regarding input in UserWidget, especially the initialisation of the InputComponent.

Before, I was manually calling InitializeInputComponent function, and then bind my action like that :

Super::InitializeInputComponent();

if (TObjectPtr<UEnhancedInputComponent> EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(InputComponent))
{
	EnhancedInputComponent->BindAction(MyAction, ETriggerEvent::Completed, this, &UMyCustomWidget::MyFunction);
}

This call was done after the PlayerController BeginPlay finished. It was the sole workaround I found to manage to use EnhancedInput in UserWidget, otherwise the InputComponent was always nullptr.

But with 5.7, the following deprecation warning appeared :

"InitializeInputComponent is deprecated. bAutomaticallyRegisterInputOnConstruction will be set on compilation of this widget and automatically create the input component instead."

So I checked this bAutomaticallyRegisterInputOnConstruction boolean in the source code, and tried two things :

  • Set its value to true in the constructor
UMyCustomWidget::UMyCustomWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
	bAutomaticallyRegisterInputOnConstruction = true;
}
  • Manually set it to true in NativeOnInitialized BEFORE calling super
void UMyCustomWidget::NativeOnInitialized()
{
	bAutomaticallyRegisterInputOnConstruction = true;
	Super::NativeOnInitialized();
    [...]
}

But this line of source code is ruining everything, and I don’t know how to properly bypass it :

void UUserWidget::CreateInputComponent()
{
	[...]
	// The widget tree may be constructed from instanced subobjects so we need to set this value
	// based on this widget's actual CDO.
	if (!HasAnyFlags(RF_ClassDefaultObject))
	{
		const UUserWidget* DefaultWidget = CastChecked<UUserWidget>(GetClass()->GetDefaultObject());
		bAutomaticallyRegisterInputOnConstruction = DefaultWidget->bAutomaticallyRegisterInputOnConstruction;
	}
	[...]
}

bAutomaticallyRegisterInputOnConstruction is always set back to false, because it’s its value in the DefaultWidget, and it aborts the creation of the InputComponent.
I have a BP child of this class, which is what I instantiate, but I didn’t find any trace of this property.

For now, I found a workaround by manually set the DefautObject bAutomaticallyRegisterInputOnConstruction to false BEFORE calling Super::NativeOnInitialized(), but it seems way too shady as a fix to be the proper way to do it.

void UMyCustomWidget::NativeOnInitialized()
{
	UUserWidget* DefaultWidget = CastChecked<UUserWidget>(GetClass()->GetDefaultObject());
	DefaultWidget->bAutomaticallyRegisterInputOnConstruction = true;

	Super::NativeOnInitialized();
    [...]
}

Any idea ? :smiling_face_with_tear:

Thanks !