[Verse Enhanced Input] Inputs APIs are no longer sending input events

Summary

Both UnrealEngine.ControlInput & Verse.Input modules are not sending any input events when the InputMappingContext is added and the InputAction triggered by the player.

Please select what you are reporting on:

Unreal Editor for Fortnite

What Type of Bug are you experiencing?

Verse

Steps to Reproduce

  • Create an entity and add a basic_interactable_component and the GameInputQAComponent:
GameInputQAComponent := class<final_super>(component) {
    @editable bUseDeprecatedAPI<public>:logic = false;
    @editable InputAction<public>:input_action(logic);
    @editable InputMappingContext<public>:input_mapping;

    OnSimulate<override>()<suspends>:void = {
        Interactable := Self.Entity.GetComponent[(/Verse.org:)SceneGraph.basic_interactable_component] or Err("SceneGraph.basic_interactable_component");

        Agent:agent = Interactable.SucceededEvent.Await();
        Player := player[Agent] or Err("[GameInputQAComponent]: Player required");

        if (Self.bUseDeprecatedAPI?) {
            PlayerInput := (/UnrealEngine.com:)ControlInput.GetPlayerInput[Player] or Err("Input.GetPlayerInput");

            PlayerInput.AddInputMapping(Self.InputMappingContext);
            InputEvents := PlayerInput.GetInputEvents(Self.InputAction);

            loop {
                Event:string = race {
                    (InputEvents.ActivationTriggeredEvent.Await(); "ActivationTriggered");
                    (InputEvents.ActivationCanceledEvent.Await(); "ActivationCanceled");
                    (InputEvents.DetectionBeginEvent.Await(); "DetectionBegin");
                    (InputEvents.DetectionOngoingEvent.Await(); "DetectionOngoing");
                    (InputEvents.DetectionEndEvent.Await(); "DetectionEnd");  
                };

                Print("[GameInputQAComponent(UnrealEngine.ControlInput)]: {Event}");
            };
        } else {
            PlayerInput := (/Verse.org:)Input.GetPlayerInput[Player] or Err("Input.GetPlayerInput");

            PlayerInput.AddInputMapping(Self.InputMappingContext);
            InputEvents := PlayerInput.GetInputEvents(Self.InputAction);

            loop {
                Event:string = race {
                    # Uses Sleep() to suprress LSP Error: `Expected async expression and only found immediate expression.`
                    (InputEvents.TriggerActivationEvent.Await(); Sleep(-1.0); "TriggerActivation");
                    (InputEvents.CancelActivationEvent.Await(); Sleep(-1.0); "CancelActivation");
                    (InputEvents.BeginDetectEvent.Await(); Sleep(-1.0); "BeginDetect");
                    (InputEvents.DetectionOngoingEvent.Await(); Sleep(-1.0); "DetectionOngoing");
                    (InputEvents.EndDetectEvent.Await(); Sleep(-1.0); "EndDetect");
                };

                Print("[GameInputQAComponent(Verse.Input)]: {Event}");
            };
        }
    };
};
  • Start the game
  • Interact with the entity and trigger the input you selected

Expected Result

We should see a output logs after the player presses the input.

Observed Result

Nothing happens.

Platform(s)

Windows 11 - 40.10-CL-52157884

The status of FORT-1087273 changed to ‘Needs Triage’. We’ve confirmed the issue and it’s waiting to be assigned to someone to fix it.

Hey! I’m curious why you are using a loop and awaiting rather than subscribing to the actions?

            PlayerInput := (/Verse.org:)Input.GetPlayerInput[Player] or Err("Input.GetPlayerInput");

            PlayerInput.AddInputMapping(Self.InputMappingContext);

            InputEvents := PlayerInput.GetInputEvents(Self.InputAction);


            InputCancelable := InputEvents.TriggerActivationEvent.Subscribe(LogicInputTriggered)

            InputCancelableDetectBegin := InputEvents.BeginDetectEvent.Subscribe(LogicInputBegin)

            InputCancelableDetectEnd := InputEvents.EndDetectEvent.Subscribe(LogicInputEnd)


    LogicInputTriggered(Arg:tuple(player, logic)):void=
            NameMessage:= MessageMaker()
            PlayerName:=MakeAgentName(Arg(0))
            Print("{InputName} {Localize(PlayerName)} fired at {GetSimulationElapsedTime()}.")

    LogicInputBegin(Arg:tuple(player, logic)):void=
        Print("Input Trigger BEGIN (verse) Fired at {GetSimulationElapsedTime()}.")

    LogicInputEnd(Arg:tuple(player, float)):void=
        Print("Input Trigger END (verse) Fired at {GetSimulationElapsedTime()}.")

Doing something like that should work.

Did this workflow work for you in 40.10?

1 Like

Hey!

Just tested on 40.20-CL-524632 and that snippet worked but so did my awaits,
lot of us use await over subscribe for easy cancelling and such.
So it looks like the events only gets sent once you use dummy Subscribe(), which is very much not ideal.


<# ...Same code... #>
InputEvents := PlayerInput.GetInputEvents(Self.InputAction);

# ✅ Now TriggerActivationEvent below works!
InputCancelable := InputEvents.TriggerActivationEvent.Subscribe(LogicInputTriggered);

# ❌ Not Subscribing: BeginDetectEvent below will not fire
# InputCancelableDetectBegin := InputEvents.BeginDetectEvent.Subscribe(LogicInputBegin);

# ❌ Not Subscribing: EndDetectEvent below will not fire
# InputCancelableDetectEnd := InputEvents.EndDetectEvent.Subscribe(LogicInputEnd);

loop {
    Event:string = race {
        # Uses Sleep() to suprress LSP Error: `Expected async expression and only found immediate expression.`
        (InputEvents.TriggerActivationEvent.Await(); Sleep(-1.0); "TriggerActivation");
        (InputEvents.CancelActivationEvent.Await(); Sleep(-1.0); "CancelActivation");
        (InputEvents.BeginDetectEvent.Await(); Sleep(-1.0); "BeginDetect");
        (InputEvents.DetectionOngoingEvent.Await(); Sleep(-1.0); "DetectionOngoing");
        (InputEvents.EndDetectEvent.Await(); Sleep(-1.0); "EndDetect");
    };

    Print("[GameInputQAComponent(Verse.Input)]: {Event}");
};

<# They dont need to do anything #>
LogicInputTriggered(Arg:tuple(player, logic)):void = {};
LogicInputBegin(Arg:tuple(player, logic)):void = {};
LogicInputEnd(Arg:tuple(player, float)):void = {};

As soon as Subscribe() is used, everything works properly.

@Andyland