Button held logic. I feel like i'm missing something

I am just playing around with the new input system and I am trying to grasp how it handles button holding.

I have set up the button like so…

How do I go about triggering different logic between when the button is held vs pressed?

As an example, a standard attack from a character, vs a charged up attack when held…

Below is what I have so far but I feel like I’m missing something with the new input system.

    private ControllerMap _controlMap;

    private IEnumerator ButtonHeld;
   
    void Awake()
    {
        _controlMap = new ControllerMap();
        _controlMap.CharacterControl.SetCallbacks(this);
    }

    void OnEnable()
    {
        _controlMap.CharacterControl.South.Enable();
    }

    void OnDisable()
    {
        _controlMap.CharacterControl.South.Disable();
    }

    public void OnSouth(InputAction.CallbackContext context)
    {

        if (context.started)
        {
            if (ButtonHeld != null)
            {
                StopCoroutine(ButtonHeld);
            }
            ButtonHeld = SouthHeld();
            StartCoroutine(ButtonHeld);
        }

        if (context.canceled)
        {
           
            if (ButtonHeld != null)
            {
                StopCoroutine(ButtonHeld);
            }
            if (context.time - context.startTime < 0.3)
            {
                Debug.Log("X pressed logic");
            }
            else
            {
                Debug.Log("X no longer held");
            }
          
        }

    }
    private IEnumerator SouthHeld()
    {
        yield return new WaitForSeconds(0.3f);
        Debug.Log("X held logic");
    }

I’d use two separate input actions: one for the button being pressed and the other for the button being held. That way you can keep the pressed and held logic separate from each other.

1 Like

Oh i see! I was treating actions like potential buttons/axis being used and not using it like potential actions. Thanks for that!

Just to add that, it is possible to have this sitting on the same binding. Interactions can be stacked, though not every combination makes sense. The system goes through the interactions top down and interactions higher up the stack get to drive an action before interactions lower down the stack do.

Anyway, here is an example of a fire action where the button can be tapped for immediate firing or held for charged firing. This is adapted from SimpleDemo.

// Note the two interactions. "tap" will require a press-and-release within tap time.
// If the button is held for longer, the action automatically transitions into a "slowTap".
var fireAction = new InputAction(name: "fire",
    binding: "<Gamepad>/buttonSouth",
    interactions: "tap;slowTap");

fireAction.performed +=
    ctx =>
{
    if (ctx.interaction is SlowTapInteraction)
    {
        StartCoroutine(BurstFire((int)(ctx.duration * burstSpeed)));
    }
    else
    {
        Fire();
    }
    m_Charging = false;
};
fireAction.started +=
    ctx =>
{
    if (ctx.interaction is SlowTapInteraction)
        m_Charging = true;
};
fireAction.canceled +=
    ctx =>
{
    m_Charging = false;
};