It packages and works at run time in the package. I agree that there is definitely a more sensible way of accomplishing this like just using timers. However, if you really need the input to control the frequency at which an action occurs because the action needs to be decoupled in that way. Then this works fine.
My understanding is that the Input Action data asset is a config file(?) when you make a change to the config file it doesn’t do anything until UE flushes what it knows about the input mapping context, and rebuilds it from the config file. Could be wrong, though.
Here’s a quick player controller I threw together so you can look at it yourself. Sorry, I don’t know a better way to easily share this.
In the editor make an Input Action named IA_PrimaryFire with a pulse trigger, and an Input Mapping Context named IMC_InGame with IA_PrimaryFire mapped to it.
Derive a blueprint from the MyPlayerController.cpp class. In the World Settings of the level make sure you are setting this derived player controller as the player controller to use. In the details populate it with the IMC and IA you just made. Then on BeginPlay call UpdateFiringInterval pass in IA_PrimaryFire, and set the float to 0.5. Then add a delay for a few seconds and call the function again with a different float like 5.0. In the log while the input action is active it’ll output 0.5 every 0.5 seconds. After the delay is done it will output 5.0 every 5 seconds.
MyPlayerController.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "InputActionValue.h"
#include "EnhancedInputSubsystemInterface.h"
#include "MyPlayerController.generated.h"
class UInputMappingContext;
class UInputAction;
class UEnhancedInputComponent;
UCLASS()
class YOUR_API AMyPlayerController : public APlayerController
{
GENERATED_BODY()
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Enhanced Inoput")
FModifyContextOptions Options;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Enhanced Input")
class UInputMappingContext* IMC_InGame;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Enhanced Input")
UInputAction* IA_PrimaryFire;
public:
// Called to bind functionality to input
virtual void SetupInputComponent() override;
/**
* Take in an Input Action that has a Pulse Trigger.
* Change the Pulse Triggers Interval
* Flush and rebuild the Input Mapping Context to apply the changes to the Pulse Trigger
*
* @param IA_Trigger Input Action that contains a Pulse Trigger in its Trigger Array at element 0
* @param NewInterval The new timing in seconds to set the Pulse Trigger Interval to
*/
UFUNCTION(BlueprintCallable, Category = "State")
void UpdateFiringInterval(UInputAction* IA_Trigger, float NewInterval);
UFUNCTION(BlueprintCallable, Category = "Input Actions")
void PrimaryFire(const FInputActionValue& Value);
private:
UEnhancedInputComponent* EnhancedInputComponent;
};
MyPlayerController.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyPlayerController.h"
#include "InputMappingContext.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "Components/InputComponent.h"
#include "InputTriggers.h"
#include "Kismet/GameplayStatics.h"
void AMyPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
// Get/Validate Local Player Subsystem
// Add Mapping Context -- Default is IMC_InGame
UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>
(GetLocalPlayer());
if(Subsystem)
{
Subsystem->ClearAllMappings();
Subsystem->AddMappingContext(IMC_InGame, 0);
}
// Get/Validate Enhanced Input Component
// Set Input Action Bindings
EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(InputComponent);
if(EnhancedInputComponent)
{
EnhancedInputComponent->BindAction(
IA_PrimaryFire,
ETriggerEvent::Triggered,
this,
&AMyPlayerController::PrimaryFire
);
}
}
void AMyPlayerController::UpdateFiringInterval(UInputAction* IA_Trigger, float NewInterval)
{
// Need to validate parameters
// Set the Pulse Trigger to the new Interval
Cast<UInputTriggerPulse>(IA_Trigger->Triggers[0])->Interval = NewInterval;
// Flush and rebuild the IMC - Must be flushed in order for Interval change to take effect
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>
(GetLocalPlayer())->RequestRebuildControlMappings
(
Options,
EInputMappingRebuildType::RebuildWithFlush
);
}
void AMyPlayerController::PrimaryFire(const FInputActionValue &Value)
{
{
const bool CurrentValue = Value.Get<bool>();
if(CurrentValue)
{
UE_LOG(LogTemp, Warning, TEXT("%f"), Cast<UInputTriggerPulse>(IA_PrimaryFire->Triggers[0])->Interval);
}
}
}
For testing a package just launch the .exe from a command line with the -log flag.