Bind action dynamically to EnhancedInputComponent

Hi all,

Recently I spent some time digging into the new Enhanced Input in combination to the GameplayAbilityComponent.

I successfully reached a point where I can assign ability at runtime and dinamically call said ability triggering an EnhancedInputAction


MyCharacter.cpp - SetupPlayerInputComponent
(where the input action is binded to MyCharacter function)

void AMyCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
	if(UEnhancedInputComponent* PlayerEnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent))
	{
		PlayerEnhancedInputComponent->BindAction(MovementAction.InputAction, ETriggerEvent::Triggered, this, &AMyCharacter::Movement);
	}
if(AbilitySystemComponent)
		{
			const FGameplayAbilityInputBinds Binds("Confirm", "Cancel", "ECustomAbilityInputAbilityID", static_cast<int32>(ECustomAbilityInputAbilityID::Confirm), static_cast<int32>(ECustomAbilityInputAbilityID::Cancel));
			AbilitySystemComponent->BindAbilityActivationToInputComponent(PlayerEnhancedInputComponent, Binds);
		}
}

MyCharacter.cpp - GiveAbility
(the function called at runtime to give an ability to my character)

void AMyCharacter::GiveAbility(TSubclassOf<UMyEnhancedInputAbility> StartupAbility)
{
	AbilitySystemComponent->GiveAbility(
				FGameplayAbilitySpec(StartupAbility, 1, static_cast<int32>(StartupAbility.GetDefaultObject()->AbilityInputID), this));
}

MyCharacter.cpp - SendEnhancedInputToAbilitySystemComponent
(a glue function which enable calling an ability by an EnhancedInputAction triggered. So far it only handles keyPressed and KeyReleased)

void AMyCharacter::SendEnhancedInputToAbilitySystemComponent(bool bIsPressed, const ECustomAbilityInputAbilityID AbilityInputID)
{
	if(!AbilitySystemComponent) { UKismetSystemLibrary::PrintString(this, "AbilitySystemComponent not found"); return; }
	if(bIsPressed)
	{
		UKismetSystemLibrary::PrintString(this, "Input pressed");
		AbilitySystemComponent->AbilityLocalInputPressed(static_cast<int32>(AbilityInputID));
	}
	else
	{
		UKismetSystemLibrary::PrintString(this, "Input released");
		AbilitySystemComponent->AbilityLocalInputReleased(static_cast<int32>(AbilityInputID));
	}
}

So far so good; in myCharacter blueprint i set one or more enhancedInputActions and, at runtime, if some object gave me an ability mapped to be triggered by a given InputAction it works as expected.

Now I would like to take a step forward: avoid to hardcode mapping for every inputAction like this line of code

PlayerEnhancedInputComponent->BindAction(MovementAction.InputAction, ETriggerEvent::Triggered, this, &AMyCharacter::Movement);

Instead it would be nice to have some kind of struct which contains all the necessary infos (InputAction, ETriggerEvent, Object, BindedFunctionToCall).

So my questions are:

  1. Is it conceptually possible to create a struct which contains all theese informations?
  2. Is this the best way to do it or there are some different ways/ patterns to look for?

The hardest part I’m facing is the one relative to passing the reference of an object’s function to bind to.

Thanks in advance for your time :slight_smile:

Luca