Skip to content

Input Handlers

Input Handlers are the worker classes in this framework. The can decide if they are compatible with a certain combination of Input Action and Trigger Event and if so, then they will receive the input values from such event and deal with them.

For that decision process, they always require one or many Input Actions and trigger events for these actions. Optionally, Input Handlers can be buffered for later usage and more details on that can be found in the Input Buffer section.

They are made available to the UNinjaInputManagerComponent class via the UNinjaInputSetupDataAsset container, meaning they can be added or removed in conjunction with an Input Mapping Context.

Properties

Every Input Handler will extend from the UNinjaInputHandler class. By doing so, they will inherit the following properties, that can be filled either by subclasses/blueprints or when they are added to the Data Asset.

  • Input Actions: All the Input Actions that this Handler is compatible with.
  • Trigger Events: For the provided Actions, which Trigger Events should be watched.
  • Can Be Buffered: Can this Handler be saved in the Input Bufffer for later use?
Trigger Events

We can only capture Trigger Events that are tracked by the system, as defined in the Settigns Page. For more information, please check the Initial Setup page.

Where to set values?

You can decide which one is more appropriate for your use-case but generally speaking, if you have a very especialized Input Handler, such as the Character Handlers provided by the plugin, it could make sense to bind the expected values right away, via C++ or Blueprints.

However, if you have more abstract ones, such as the G.A.S. Handlers provided by the plugin, then it's not possible to foresee all these values and having them set in the Data Asset, once they are applied, makes more sense.

Input Handler Properties (Blueprint)

// ---
// .cpp
UInputHandler_Move::UInputHandler_Move()
{
    TriggerEvents.Add(ETriggerEvent::Triggered);
    TriggerEvents.Add(ETriggerEvent::Ongoing);

    static ConstructorHelpers::FObjectFinder<UInputAction> InputActionRef(TEXT("/Script/EnhancedInput.InputAction'/NinjaInput/Input/IA_Move.IA_Move'"));
    if (InputActionRef.Succeeded())
    {
        const TObjectPtr<UInputAction> InputAction = InputActionRef.Object;
        InputActions.AddUnique(InputAction);
    }
}

Input Handler Properties (Data Asset)

Functions

A Handler has a few functions that can be overrided to implement specific behavior. They can be extended either in C++ or Blueprints.

Compatibility Test Function

The first relevant Function provided by Handlers is the CanHandle which is invoked by the Input Manager to determine the Handler's compatibility with a combination of Input Actions + Trigger Event.

It already implements that behaviour by default and you only need to change it if you want something more elaborate than that. Keep in mind though that the input parameters won't give you access to the context.

Contextual Tests

The Handler test only determines if the Handle can operate on a certan Action and Trigger. It should not determine transitive circumstances such as "can the character move?" or "can the character attack?". These will either go to the dedicated Handle function or to an external object, such as a Gameplay Ability.

Marking it as Final

If you extend this function (or actually any others), it may be worth considering marking them final if no sub-classes are going to change the behavior further as this will provide some optimization gains.

Input Handler Test Function (Blueprint)

// ---
// .h

// Custom compatibility check, marked as final for optimization.
virtual bool anHandle_Implementation(const ETriggerEvent& TriggerEvent, 
    const UInputAction* InputAction) final const override;

// ---
// .cpp

bool UNinjaInputHandler::CanHandle_Implementation(const ETriggerEvent& TriggerEvent,
    const UInputAction* InputAction) const
{
    return TriggerEvent != ETriggerEvent::None && IsValid(InputAction) &&
        InputActions.Contains(InputAction) && TriggerEvents.Contains(TriggerEvent);
}

Handler Functions

Once a Handler has been activated, it will ultimately invoke one of its dedicated Handler functions, which can be extended to implement the intended behaviour.

These functions are to access their contexts through the provided UNinjaInputManagerComponent reference.

Input Handler Test Function (Blueprint)

virtual void HandleTriggeredEvent_Implementation(
    UNinjaInputManagerComponent* Manager, 
    const FInputActionValue& Value, 
    const UInputAction* InputAction) const override;

virtual void HandleStartedEvent_Implementation(
    UNinjaInputManagerComponent* Manager, 
    const FInputActionValue& Value, 
    const UInputAction* InputAction) const override;

virtual void HandleOngoingEvent_Implementation(
    UNinjaInputManagerComponent* Manager, 
    const FInputActionValue& Value, 
    const UInputAction* InputAction) const override;

virtual void HandleCancelledEvent_Implementation(
    UNinjaInputManagerComponent* Manager, 
    const FInputActionValue& Value, 
    const UInputAction* InputAction) const override;

virtual void HandleCompletedEvent_Implementation(
    UNinjaInputManagerComponent* Manager, 
    const FInputActionValue& Value, 
    const UInputAction* InputAction) const override;
Implementing Functions

You only need to implement the functions related to events being tracked by your handler.