Enhanced Input System: when are input actions set to be executed

For context, I am trying to recreate the pistol from the VR template in C++. I have been able to do this; however, certain aspects of the enhanced input system are not entirely clear to me.

From the constructor of the Pistol class, I call the function SetupPistolInputActions(). Inside this function, I bind the IA_Shoot_Left and IA_Shoot_Right input actions to the functions that I want to be executed when these events are triggered. I noticed that for the IA_Shoot_Left, I didn’t have to load the input action, which was defined in Blueprint, because it was already loaded, while for the IA_Shoot_Right, I had to explicitly load the Blueprint input action. How is this possible? For now, I load both input actions explicitly, just to be safe.

When I run the application, I used the showdebug enhancedinput command to see what was happening when I pressed the buttons related to the pistol. I noticed that when I pressed the buttons coupled with the IA_Shoot_Left and IA_Shoot_Right input actions, the inputs were triggered; however, the functions bound to these inputs were not executed. This only happens after I pick up the weapon and add the input mapping context. What exactly does adding the input mapping context do? Does this enable the propagation of the input action to the function it is bound to?

Finally, is it possible to bind two input actions to one function and use a parameter to distinguish which input action called the function, or is this considered not done?

I can answer this from a blueprint perspective, which is very similar in concept.

It’s up to you what input actions you include in a class. IA_Shoot may not be there at all when you start, if you want to include it, you can.

It makes sense that nothing works without a mapping context, because the mapping is a translation from your input to the events. Say I want to use X as IA_Shoot_Left and ‘Spacebar’ as IA_Shoot_right, the system doesn’t know this until I add the mapping context, and it makes no sense to respond while the mapping is missing.

As for passing parameters, there are a lot of parameters returned with the event itself, but if you want to pass specific parameters yourself, its probably easier to incorporate the IA… events in the player controller, and use that to call different events ( using an interface for example ) in the corresponding class.

What do you exactly mean with including it? In the VR template the input actions IA_Shoot_Left and IA_Shoot_Right are defined in Blueprint. Do I need to include them in C++ or does the UHT links this as long as I define the input actions as UPROPERTIES?

Why is it then that the showdebug enhancedinput command highlights the input actions when I press the buttons assigned to these input actions in the input mapping context when this input mapping context is not yet added? This confuses me.

Can you elaborate on this part? I don’t understand it completely.

It sounds like you’re working with Unreal Engine’s Enhanced Input System in C++. Let’s break down the questions you’ve raised.

1. Why didn’t you need to load the input action for IA_Shoot_Left, but did for IA_Shoot_Right?

This discrepancy could be due to the way input actions are being initialized or referenced in your Blueprint. If the IA_Shoot_Left input action is already being loaded or referenced somewhere in your Blueprint (perhaps in the Player Controller, Pawn, or a different component that initializes it), it may be automatically available when you create the bindings in C++. On the other hand, if IA_Shoot_Right isn’t referenced or loaded in a similar way, you’d need to explicitly load it in C++.

To be safe, loading both input actions explicitly in your C++ code, as you’re doing now, is a good practice. This ensures that both input actions are correctly loaded and available when you need them.

2. What does adding the input mapping context do?

Adding an Input Mapping Context is crucial in the Enhanced Input System. The input system uses contexts to manage and prioritize input bindings. When you add an input mapping context to a player or a component, you’re effectively enabling the system to recognize and process the input actions defined within that context.

Until you add the input mapping context, the input actions bound in your code might not be recognized by the input system, which is why your bound functions are not executed. Adding the context tells the input system to “listen” for those specific input actions and allows the propagation of the input to the functions you’ve bound.

In short, adding the input mapping context enables the input system to recognize and process the input actions, which then triggers the bound functions.

3. Is it possible to bind two input actions to one function and use a parameter to distinguish between them?

Yes, it is possible to bind multiple input actions to a single function. You can distinguish between the input actions by passing a parameter to the function. One approach is to create a wrapper function that takes an identifier (like an enum or a specific value) as a parameter, indicating which input action triggered the call.

Here’s a simple example:

cpp

Copy code

void APistol::HandleShootInput(FString InputActionName)
{
    if (InputActionName == "IA_Shoot_Left")
    {
        // Handle left shoot
    }
    else if (InputActionName == "IA_Shoot_Right")
    {
        // Handle right shoot
    }
}

You can bind the input actions like this:

cpp

Copy code

PlayerInputComponent->BindAction(IA_Shoot_Left, ETriggerEvent::Triggered, this, &APistol::HandleShootInput).WithLambda([this]() { HandleShootInput("IA_Shoot_Left"); });
PlayerInputComponent->BindAction(IA_Shoot_Right, ETriggerEvent::Triggered, this, &APistol::HandleShootInput).WithLambda([this]() { HandleShootInput("IA_Shoot_Right"); });

This way, the function HandleShootInput knows which input action triggered the call based on the parameter passed to it Vantage ADP.

This approach is valid and often used when you want to consolidate similar functionality but distinguish between different input sources. While it might add some complexity, it can reduce code duplication and help centralize input handling logic.

Thank you for a useless ChatGPT reply. The first answer I can do something with, I will give you that. The second answer partially answers my question and the last answer is completely false. There is no such thing as a WriteLambda() function in the FEnhancedInputActionEventBinding struct.

By using the reference viewer in the Unreal Editor, I discovered a hard reference to the IA_Shoot_Left input action in the VRTemplateMap. I removed some custom Blueprints from the level and then added them back, which eliminated the hard reference. I believe this hard reference was the reason why the IA_Shoot_Left input action was being loaded prematurely.

My reasoning was way off here. It had nothing to do with the input mapping context. The function I wanted to execute was a server RPC. As long as the pistol was not grabbed, it had no owner, and as a result, the server RPC could not be executed. In the Output Log, I also received the following warnings:

LogNet: Warning: UNetDriver::ProcessRemoteFunction: No owning connection for actor CustomPistol_0. Function ServerShootLeft will not be processed.
LogNet: Warning: UNetDriver::ProcessRemoteFunction: No owning connection for actor CustomPistol_1. Function ServerShootLeft will not be processed.
LogNet: Warning: UNetDriver::ProcessRemoteFunction: No owning connection for actor CustomPistol_0. Function ServerShootRight will not be processed.
LogNet: Warning: UNetDriver::ProcessRemoteFunction: No owning connection for actor CustomPistol_1. Function ServerShootRight will not be processed.

Additionally, the Input Mapping Contexts were applied immediately when the EI subsystem was ready. This was because the “Add Immediately” option was checked under Project Settings > Engine > Enhanced Input > Default Mapping Contexts.

I didn’t find the exact answer I was looking for; however, some suggestions are provided in this post. For now, I still use separate functions for each input action.