InitialButtonRepeatDelay

InitialButtonRepeatDelay

#Overview

name: InitialButtonRepeatDelay

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 14 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of InitialButtonRepeatDelay is to set the initial delay before a button press starts repeating when held down. This setting is used in various input systems across different platforms and devices in Unreal Engine 5.

InitialButtonRepeatDelay is primarily used in input-related subsystems and modules, including:

  1. OpenXR Input Plugin
  2. Steam Controller Plugin
  3. XInput Device Plugin (for Windows)
  4. Android Input Interface
  5. HID Input Interface (for Mac)

The value of this variable is typically set in the engine configuration file (GInputIni) under the “/Script/Engine.InputSettings” section. It’s usually read at the initialization of the respective input interfaces or controllers.

InitialButtonRepeatDelay often interacts with another variable called ButtonRepeatDelay, which determines the delay between subsequent repeats after the initial delay.

Developers should be aware that:

  1. This variable affects the responsiveness of button inputs in various input systems.
  2. Different platforms or input devices may have different default values or ways of handling this setting.
  3. Modifying this value can impact the user experience, especially in games that rely heavily on repeated button presses.

Best practices when using this variable include:

  1. Ensure the value is appropriate for your game’s input requirements and user experience goals.
  2. Test the setting across different platforms and input devices to ensure consistent behavior.
  3. Consider exposing this setting to users in the game’s options menu, allowing them to customize it to their preferences.
  4. Be cautious when changing this value, as it may affect gameplay mechanics that rely on specific button repeat timings.
  5. Document any custom values used in your project to maintain consistency across the development team.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseInput.ini:19, section: [/Script/Engine.InputSettings]

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Plugins/Runtime/OpenXR/Source/OpenXRInput/Private/OpenXRInput.cpp:959

Scope (from outer to inner):

file
function     void FOpenXRInputPlugin::FOpenXRInput::SendControllerEvents

Source code excerpt:

					}

					Action.NextRepeatTime = State.lastChangeTime + InitialButtonRepeatDelay;

					FXRTimedInputActionDelegate* const Delegate = OpenXRInputNamespace::GetTimedInputActionDelegate(Action.Name);
					if (Delegate)
					{
						Delegate->Execute(State.currentState ? 1.0 : 0.0f, ToFTimespan(State.lastChangeTime));
					}

#Loc: <Workspace>/Engine/Plugins/Runtime/OpenXR/Source/OpenXRInput/Private/OpenXRInput.h:176

Scope (from outer to inner):

file
class        class FOpenXRInputPlugin : public IOpenXRInputPlugin
class        class FOpenXRInput : public IOpenXRInputModule, public IInputDevice, public FXRMotionControllerBase, public IHapticDevice, public TSharedFromThis<FOpenXRInput>

Source code excerpt:


		/** Repeat key delays */
		const XrTime InitialButtonRepeatDelay = 2e8;
		const XrTime ButtonRepeatDelay = 1e8;

		bool BuildActions(XrSession Session);
		void SyncActions(XrSession Session);
		void BuildLegacyActions(TMap<FString, FInteractionProfile>& Profiles);
		void BuildEnhancedActions(TMap<FString, FInteractionProfile>& Profiles);

#Loc: <Workspace>/Engine/Plugins/Runtime/Steam/SteamController/Source/SteamController/Private/SteamController.cpp:26

Scope (from outer to inner):

file
class        class FSteamController : public IInputDevice
function     FSteamController

Source code excerpt:


	FSteamController(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler) :
		InitialButtonRepeatDelay(0.2),
		ButtonRepeatDelay(0.1),
		MessageHandler(InMessageHandler),
		bSteamControllerInitialized(false),
		InputSettings(nullptr)
	{
		GConfig->GetDouble(TEXT("/Script/Engine.InputSettings"), TEXT("InitialButtonRepeatDelay"), InitialButtonRepeatDelay, GInputIni);
		GConfig->GetDouble(TEXT("/Script/Engine.InputSettings"), TEXT("ButtonRepeatDelay"), ButtonRepeatDelay, GInputIni);

		// Initialize the API, so we can start calling SteamController functions
		SteamAPIHandle = FSteamSharedModule::Get().ObtainSteamClientInstanceHandle();

		// [RCL] 2015-01-23 FIXME: move to some other code than constructor so we can handle failures more gracefully

#Loc: <Workspace>/Engine/Plugins/Runtime/Steam/SteamController/Source/SteamController/Private/SteamController.cpp:322

Scope (from outer to inner):

file
class        class FSteamController : public IInputDevice

Source code excerpt:


	/** Delay before sending a repeat message after a button was first pressed */
	double InitialButtonRepeatDelay;

	/** Delay before sending a repeat message after a button has been pressed for a while */
	double ButtonRepeatDelay;

	/** handler to send all messages to */
	TSharedRef<FGenericApplicationMessageHandler> MessageHandler;

#Loc: <Workspace>/Engine/Plugins/Runtime/Windows/XInputDevice/Source/XInputDevice/Private/XInputInterface.cpp:42

Scope (from outer to inner):

file
function     XInputInterface::XInputInterface

Source code excerpt:

	bIsGamepadAttached = false;
	bNeedsControllerStateUpdate = true;
	InitialButtonRepeatDelay = 0.2f;
	ButtonRepeatDelay = 0.1f;

	GConfig->GetFloat(TEXT("/Script/Engine.InputSettings"), TEXT("InitialButtonRepeatDelay"), InitialButtonRepeatDelay, GInputIni);
	GConfig->GetFloat(TEXT("/Script/Engine.InputSettings"), TEXT("ButtonRepeatDelay"), ButtonRepeatDelay, GInputIni);

	// In the engine, all controllers map to xbox controllers for consistency 
	X360ToXboxControllerMapping[0] = 0;		// A
	X360ToXboxControllerMapping[1] = 1;		// B
	X360ToXboxControllerMapping[2] = 2;		// X

#Loc: <Workspace>/Engine/Plugins/Runtime/Windows/XInputDevice/Source/XInputDevice/Private/XInputInterface.cpp:258

Scope (from outer to inner):

file
function     void XInputInterface::SendControllerEvents

Source code excerpt:

					if ( CurrentStates[ButtonIndex] != 0 )
					{
						// this button was pressed - set the button's NextRepeatTime to the InitialButtonRepeatDelay
						ControllerState.NextRepeatTime[ButtonIndex] = CurrentTime + InitialButtonRepeatDelay;
					}
				}
				else if ( CurrentStates[ButtonIndex] != 0 && ControllerState.NextRepeatTime[ButtonIndex] <= CurrentTime )
				{
					MessageHandler->OnControllerButtonPressed( Buttons[ButtonIndex], PlatformUser, InputDevice, true );

#Loc: <Workspace>/Engine/Plugins/Runtime/Windows/XInputDevice/Source/XInputDevice/Private/XInputInterface.h:131

Scope (from outer to inner):

file
class        class XInputInterface : public IInputDevice

Source code excerpt:


	/** Delay before sending a repeat message after a button was first pressed */
	float InitialButtonRepeatDelay;

	/** Delay before sending a repeat message after a button has been pressed for a while */
	float ButtonRepeatDelay;

	/**  */
	FGamepadKeyNames::Type Buttons[MAX_NUM_CONTROLLER_BUTTONS];

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Android/AndroidInputInterface.cpp:37

Scope: file

Source code excerpt:


FGamepadKeyNames::Type FAndroidInputInterface::ButtonMapping[MAX_NUM_CONTROLLER_BUTTONS];
float FAndroidInputInterface::InitialButtonRepeatDelay;
float FAndroidInputInterface::ButtonRepeatDelay;

FDeferredAndroidMessage FAndroidInputInterface::DeferredMessages[MAX_DEFERRED_MESSAGE_QUEUE_SIZE];
int32 FAndroidInputInterface::DeferredMessageQueueLastEntryIndex = 0;
int32 FAndroidInputInterface::DeferredMessageQueueDroppedCount   = 0;

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Android/AndroidInputInterface.cpp:130

Scope (from outer to inner):

file
function     FAndroidInputInterface::FAndroidInputInterface

Source code excerpt:

	ButtonMapping[MAX_NUM_PHYSICAL_CONTROLLER_BUTTONS + 7] = FGamepadKeyNames::RightStickDown;

	InitialButtonRepeatDelay = 0.2f;
	ButtonRepeatDelay = 0.1f;

	GConfig->GetFloat(TEXT("/Script/Engine.InputSettings"), TEXT("InitialButtonRepeatDelay"), InitialButtonRepeatDelay, GInputIni);
	GConfig->GetFloat(TEXT("/Script/Engine.InputSettings"), TEXT("ButtonRepeatDelay"), ButtonRepeatDelay, GInputIni);

	CurrentVibeIntensity = 0;
	FMemory::Memset(VibeValues, 0);
	
	FMemory::Memset(DeviceMapping, 0);

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Android/AndroidInputInterface.cpp:1328

Scope (from outer to inner):

file
function     void FAndroidInputInterface::SendControllerEvents

Source code excerpt:

					if (NewControllerState.ButtonStates[ButtonIndex])
					{
						// This button was pressed - set the button's NextRepeatTime to the InitialButtonRepeatDelay
						NewControllerState.NextRepeatTime[ButtonIndex] = CurrentTime + InitialButtonRepeatDelay;
					}
				}
				else if (NewControllerState.ButtonStates[ButtonIndex] && NewControllerState.NextRepeatTime[ButtonIndex] <= CurrentTime)
				{
					// Send button repeat events
					MessageHandler->OnControllerButtonPressed(ButtonMapping[ButtonIndex], UserId, DeviceId, true);

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Mac/HIDInputInterface.cpp:36

Scope (from outer to inner):

file
function     HIDInputInterface::HIDInputInterface

Source code excerpt:


	bIsGamepadAttached = false;
	InitialButtonRepeatDelay = 0.2f;
	ButtonRepeatDelay = 0.1f;

	GConfig->GetFloat(TEXT("/Script/Engine.InputSettings"), TEXT("InitialButtonRepeatDelay"), InitialButtonRepeatDelay, GInputIni);
	GConfig->GetFloat(TEXT("/Script/Engine.InputSettings"), TEXT("ButtonRepeatDelay"), ButtonRepeatDelay, GInputIni);

	Buttons[0] = FGamepadKeyNames::FaceButtonBottom;
	Buttons[1] = FGamepadKeyNames::FaceButtonRight;
	Buttons[2] = FGamepadKeyNames::FaceButtonLeft;
	Buttons[3] = FGamepadKeyNames::FaceButtonTop;

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Mac/HIDInputInterface.cpp:576

Scope (from outer to inner):

file
function     void HIDInputInterface::SendControllerEvents

Source code excerpt:

					if (CurrentButtonStates[ButtonIndex] != 0)
					{
						// this button was pressed - set the button's NextRepeatTime to the InitialButtonRepeatDelay
						ControllerState.NextRepeatTime[ButtonIndex] = CurrentTime + InitialButtonRepeatDelay;
					}
				}
				else if (CurrentButtonStates[ButtonIndex] != 0 && ControllerState.NextRepeatTime[ButtonIndex] <= CurrentTime)
				{
					MessageHandler->OnControllerButtonPressed(Buttons[ButtonIndex], UserId, DeviceId, true);

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Private/Mac/HIDInputInterface.h:113

Scope (from outer to inner):

file
class        class HIDInputInterface

Source code excerpt:


	/** Delay before sending a repeat message after a button was first pressed */
	float InitialButtonRepeatDelay;

	/** Delay before sendign a repeat message after a button has been pressed for a while */
	float ButtonRepeatDelay;

	bool bIsGamepadAttached;

#Loc: <Workspace>/Engine/Source/Runtime/ApplicationCore/Public/Android/AndroidInputInterface.h:361

Scope (from outer to inner):

file
class        class FAndroidInputInterface : public IInputInterface

Source code excerpt:

	static FGamepadKeyNames::Type ButtonMapping[MAX_NUM_CONTROLLER_BUTTONS];

	static float InitialButtonRepeatDelay;
	static float ButtonRepeatDelay;

	static FDeferredAndroidMessage DeferredMessages[MAX_DEFERRED_MESSAGE_QUEUE_SIZE];
	static int32 DeferredMessageQueueLastEntryIndex;
	static int32 DeferredMessageQueueDroppedCount;