Category: Enhanced-Input-System

Enhanced-Input-System (Basics 2)

(very much WIP)

Sections

Introduction

In the last post we looked at the main building blocks of the EIS and how they fit together. This time we will take a closer look at the TriggerEvents. We will finish it with 2 examples that will showcase the chorded action – an action that fires when 2 buttons are pressed – as well as a setup where the executed action depends on if you tap a key quickly or hold it for some time.

TriggerEvents

There are 5 TriggerEvents

  • Started: key was pressed and triggers start being evaluated
  • Ongoing: triggers still being evaluated
  • Triggered: a trigger was successful
  • Cancelled: a chorded-action or all other actions was unsuccessful *
  • Completed: one/all triggers were successful *

* this depends on the combination of triggers and their TriggerType (Explicit / Implicit)

Looking at this the first time is a little confusing and you’ll understand it much faster if you play around with some setups. You can use the showdebug enhancedinput. I find it’s an overkill for now and would recommend using a macro. You can just copy&paste this macro in your character BP and connect it accordingly to your InputAction.

Example where both IAs are on the same button. IA_Sprint has a ‘Hold’-trigger and ‘IA_Dodge’ a ‘Tap’-trigger. Because we hold the button long enough, ‘AI_Dodge’ is canceled and ‘IA_Sprint’ will trigger and complete after we let go of the button

The official documentation mentions TriggerTypes. All you have to know for now is that, except Chorded Action, they are Explicit (we will look at them when we implement custom TriggerTypes in CPP). Which means that it would be enough if one Trigger fires to transition into Completed.
For example: You have a Down & Hold trigger on your action.
You press the assigned key but don’t hold it for the necessary 1s.
You will still end up at Completed because the Down event was triggered.
**Sidenote: Triggers of AIs and IMCs will be combined

Chorded Action

Chorded Actions are for IAs that should only trigger if another IA is currently triggering.

For example: So let’s say you want a simple attack but also a strong attack if you hold the SHIFT key. You can setup an IA_SHIFT where you set the trigger to be Down and an IA_StrongAttack where you set the trigger to be a Chorded Action and select IA_SHIFT as the Chord Action.

Combine Tap and Hold actions

Let’s look at the setup for a a light attack with a Tap and a strong attack with Hold.

We have two things that we want to happen, so we need 2 IAs to execute different logic.

Now you have to assign your logic. On theSome simple logic that will make it easier to understand and print the TriggerEvents for both IAs, or AnimationMontage or do something advanced and activate your GAS ability.

Make a combo

Another TriggerEvent is the Combo which, as you might have guessed already, will allow you to specify a chain of InputActions. For now it you can’t specify a time frame to enter the key but only a maximum time that will be given in order to trigger the action

Closing

not sure where I should include modifiers. in the previous this one or the next one?

What’s next?

For my personal project UI has priority right now and therefor updates for the EIS series are on ice for now

Enhanced Input System (Basics)

My main focus is on PC so I cover only keyboard&mouse input for now, other input devices might be covered in later posts.

Sections

Introduction

The Enhanced-Input-System – which I will call EIS from now on – is the default Input System in the Unreal Engine 5.1.
The Third-Person-Template has a good example and shows how to use some parts of the EIS and I will try to give you a quick introduction.
I expect you to use UE 5.1 and thus will skip over the setup that was necessary in prior versions.

Lets first look at the parts that make up the EIS

  • InputAction(IA): are used inside the InputMappingContext
  • InputMappingContext(IMC): Holds InputActions and assigns keys to them
  • PlayerMappableInputConfig(PMIC): can bundle multiple IMCs
All/Content/ThirdPerson/Input
containing an Input-Mapping-Context
Input Actions

The simplest Input-Action IA_Jump

First let’s focus on Input-Actions and Input-Mapping-Contexts
Input-Actions enable you to specify the type and conditions that are used to execute the things you assign to them.
Look at IA_Jump as an example

IA_Jump = Digital(bool)

Because jumping is just something that will happen if a button is pressed, it’s Value Type is set Digital (bool) – meaning that it will just tell us if the button is down or not-.

IMC and the IA_Jump

In the IMC we can see that for the IA_Jump 3 different keys were assigned. Space Bar for the keyboard, Gamepad Face Button Button for the Gamepad and Touch 1 for Touchscreens.
Now that we know what an IA and IMC is, where are they used?

Default C++ implementation

If you take a look at All/Content/ThirdPerson/Blueprints/BP_ThirdPersonCharacter, select the RootComponent and look in the input-section, you will see properties for the IAs and the IMC.

The IMC has to be added to the enhanced-input-subsystem. Doing that will make the mapping between Key<->InputAction available. The final step is to bind the actual logic to the IAs (If you don’t care about CPP jump ahead)

void ATestingCharacter::BeginPlay()
{
  Super::BeginPlay();

  //Add Input Mapping Context
  if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
  {
    if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
    {
      Subsystem->AddMappingContext(DefaultMappingContext, 0);
    }
  }
}

The PlayerController gives us access to the LocalPlayer which lets us get the subsystem. Using the subsystem we bind the IMC.

void ATestingCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
  // Set up action bindings
  if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent)) 
  {
    //Jumping
    EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACharacter::Jump);
    EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
    //Moving
    EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ATestingCharacter::Move);
    //Looking
    EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ATestingCharacter::Look);
  }
}

As you can see we bind the actions to their appropriate functions. For the ETriggerEvent you just use Started/Completed (which executes the logic only once) and Triggered (fires once/multiple times, depending on actual Trigger –next post goes into detail-). You can bind it’s own function to each TriggerEvent of an IA. The JumpAction , for example, binds 2 ETriggerEvents.
You can use different function-definitions

void YourCharacter::YourFuncName()
void YourCharacter::YourFuncName(const FInputActionValue& Value)
void YourCharacter::YourFuncName(const FInputActionInstane& Instance)
void YourCharacter::YourFuncName(const FInputActionValue, float ElapsedTime, float TriggeredTime, const UInputAction* SourceAction)

choose the one appropriate for your needs, the one that will give you the most information and could be used everywhere is the following

void YourCharacter::YourFuncName(const FInputActionInstance& Instance)
{
    //your code
}

which lets you access some useful properties

FInputActionInstance
Useful properties like: ElepsedProcressedTime, ElapsedTriggerTime or Value

Blueprint setup

If you are a Blueprint programmer, you can accomplish the same things inside the Character BP.
The character, created by the template, will implement have them automatically and you would only have to add this code to characters that inherit from the base character.

In order to add the actual logic you add the node for your IA (type it’s name into the search).

If you select the event you can see the bottom left node that would appear

As you can see I use a custom macro to print an OnScreenDebugMessage when TriggerEvents fire.
Another method to debug is to use the console command showdebug enhancedinput but I recommend you to use it later. For now, the macro is a lot easier to read and understand.

Zoom functionality

Let’s create a simple IA that will allow us to zoom in and out on our character.
So the first thing we need is the InputAction with a Value Type of float because we want to move along 1-Axis (zoom in/out). And let’s assume we want this to be in it’s own IMC, so we create one and call it IMC_Tutorial .

Now we need to assign the key – in this case it’s the Mouse Wheel – to our IA.

And add the new IMC using the Enhanced-Input-Subsystem inside of our BP_ThirdPersonCharacter.

In the last step we add the logic to it

Closing

Now you have the basic understanding in order to use the EIS. To really drill it down here’s the summery of the workflow

  1. create the IAs (jump, move, sprint, attack …)
  2. (create additional IMC if needed) assign Keys->Actions
  3. add the IMCs to your Enhanced-Input-Component (if not already done)
  4. add the actual logic

This is still work in progress, so questions are very welcome.

What’s next?

We will take a closer look at the TriggerEvents of IAs and how to use them correctly. We can do a lot of different logic with the provided triggers and I will show you how to setup a chorded action and how to setup different actions depending on wether you hold or tap a button.