When using mouse inputs with Enhanced Input System, it will only report an input value from it when moving the mouse. Sometimes you want it to always report an input, similar to how a gamepad stick input works.

In other words:

  1. When user hasn’t moved the mouse, report 0
  2. If the user moves the mouse, the input value will keep being reported - ie. if the user moves the mouse 0.5 units to the left, this value will keep being reported until the use moves the mouse into another direction.

This requires a two-fold approach: Making an UInputTrigger which reports input all the time, and making a UInputModifier which “accumulates” the input value.

Setting up the UInputTrigger

This part is very simple - all you need to do is set bShouldAlwaysTick to true. In the example below, the class inherits from UInputTriggerChordAction, but you can have it inherit from any of the action types available.

//.h
UCLASS()
class MYPROJECT_API UMyInputTriggerChordTicking : public UInputTriggerChordAction
{
	GENERATED_BODY()
	
public:
	UMyInputTriggerChordTicking();
};
 
//.cpp
UMyInputTriggerChordTicking::UMyInputTriggerChordTicking()
{
	bShouldAlwaysTick = true;
}

Setting up the UInputModifier

The input trigger needs to keep track of what the input value is, so you need a property on the class to store it. The example below uses a float property, which works for inputs that use Axis1D float as their value type. If you use something else, use a different type and adjust the code accordingly.

//.h
UCLASS()
class MYPROJECT_API UMyInputModifierAccumulate : public UInputModifier
{
	GENERATED_BODY()
 
public:
	virtual FInputActionValue ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override;
 
protected:
	float AccumulatedValue = 0;
};
 
//.cpp
FInputActionValue MyInputModifierAccumulate::ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime)
{
	const float CurrentFloat = CurrentValue.Get<float>();
	AccumulatedValue += CurrentFloat;
	
	return FInputActionValue(AccumulatedValue);
}

Resetting the accumulated value when using with a chord action

A slightly different way of using the input accumulation is with chorded actions. For example, if you want to rotate a camera while the left mouse button is down, and reset the camera back to zero when the chord is released.

The accumulation reset can be done with minor modifications to the modifier code:

//.h
UCLASS()
class MYPROJECT_API UMyInputModifierChordAccumulate : public UInputModifier
{
	GENERATED_BODY()
 
public:
	virtual FInputActionValue ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime) override;
 
protected:
	float AccumulatedValue = 0;
 
	UPROPERTY(EditInstanceOnly, meta=(DisplayThumbnail=false))
	UInputAction* ChordAction;
};
 
//.cpp
FInputActionValue UMyInputModifierChordAccumulate::ModifyRaw_Implementation(const UEnhancedPlayerInput* PlayerInput, FInputActionValue CurrentValue, float DeltaTime)
{
	const FInputActionInstance* EventData = PlayerInput->FindActionInstanceData(ChordAction);
	if(EventData->GetElapsedTime() > 0)
	{
		const float CurrentFloat = CurrentValue.Get<float>();
		AccumulatedValue += CurrentFloat;
	}
	else
	{
		AccumulatedValue = 0;
	}
	
	return FInputActionValue(AccumulatedValue);
}

Note the new ChordAction property. Configure it to the chord action you use in the input mapping context. To determine if the chord is active, we can check its GetElapsedTime() value. When it’s inactive, we simply reset the accumulated value to 0.

Other things to note

The resulting movement can be quite fast, so you might also want to implement mouse sensitivity settings, which can be added as a separate modifier into the modifier chain.

Depending on how you use the input, the accumulated value can in some cases grow too large or too small, which leads to the inputs not responding when changing directions. To solve this, you can clamp the accumulated value to a range, such as -1 to 1, which would match the input range given typically by other input methods.