You can create new global Action and Axis Mappings in the Input section of the Project Settings. These are saved in the .ini files in the Config directory.
However, is it possible to create a new Action or Axis Mapping with C++ during play?
Is it possible to rebind an Action or Axis Mapping with C++ during play? (like to an additional key, or to change the key)
How do the Key Bindings options menu in unreal games work? Which API do they use?
is it possible to create a new Action or Axis Mapping with C++ during play
Not sure about this one; I once tried creating a brand new binding at runtime, but I couldn’t find a way to properly call SetupPlayerInputComponent() after that, so it didn’t work.
Is it possible to rebind an Action or Axis Mapping with C++ during play?
This is of course possible, but with a few issues I’ve come across.
UInputSettings* MyInputSettings = UInputSettings::GetInputSettings();
FInputActionKeyMapping MyActionMapping;
FInputChord NewKey; // this value can be retrieved from key selector widget
NewKey.Key = EKeys::TheKeyYouNeed;
MyActionMapping.ActionName = FName("YourActionName");
MyActionMapping.Key = NewKey;
MyInputSettings->AddActionMapping(MyActionMapping);
MyInputSettings->SaveConfig();
It’s pretty much the same with axis, just change Action by Axis in all instances, and maybe you’ll need to set MyAxisMapping.Scale to for some bindings.
Now the main issues I mentioned:
You can’t change the existing bindings, you can add new ones and remove old ones. This means that you first have to get the existing binding key, save it to a variable, add a new key, then remove the old one. If you first remove the old one and then add the new one, the input may become disabled until you restart the game and SetupPlayerInputComponent() is run again. I couldn’t see the pattern, it would happen randomly.
If you add multiple keys to the same action (like you want to have a primary and a secondary key), they will be sorted in some way. No matter what I did, I couldn’t do so that the first binding would always be [0], and the second [1]; they would change places and be inconsistent. So I finally went with separate action names for primary and secondary.
Thanks. By during play I meant kind of at runtime but not actually between BeginPlay and EndPlay.
Your code was helpful. The relevant classes are UInputSettings, which is the global and connected to the .ini, and UPlayerInput which is part of the APlayerController. It looks like UPlayerInput is setup on GameMode/GameSession RestartPlayer and ClientRestartPlayer in multiplayer.
Also see void APlayerController::InitInputSystem() and APawn::PawnClientRestart()