Rebinding operation not listening to gamepad

Hi friends, I have an issue that I’ve spent hours fruitlessly attempting to solve.

  • I have a split screen setup, that allows either keyboard or controller. Everything is working correctly here. Each player uses their own PlayerInput component.
  • Since my game is asymmetrical, I cannot use the same prefab, therefore cannot use the PlayerInputManager component. However, I’ve set up my own system that creates Input users and pairs them to devices. It is currently working great.
  • I have remapping working, but it only works with keyboard/mouse. I am trying to understand why it refuses to listen to controller input. The script listens to input, but only (and always) just listens for keyboard input when I want it to listen to the device paired with the input user.
  • If player 1 uses a keyboard and mouse and player 2 uses a controller, player 1 can remap their controls just fine. Player 2 cannot.
  • If player 1 uses a controller and player 2 uses a keyboard, player 1 cannot rebind controls. Player 2 can rebind their controls just fine.
  • In both of the above instances, the keyboard responds to the rebinding operation regardless of the player, even though the keyboard is only paired with one of the players. I have verified this through the debugger and through normal gameplay, as default controls work great. If I rebind an input to a keyboard key for the controller user, the controller user cannot use that action, since it is now bound to a key on a device that is not paired with that input user.
  • I’m calling PerformInteractiveRebinding on the player-specific input action, so I would 100% expect that the method would use the device paired with the input user containing that input action. Instead, it’s always using the keyboard, which is not desired.
  • Running Unity 2022.3 and Input System 1.7.0 (the latest available for me).

My script is the following. This is attached to every button that I want to remap, working correctly with keyboard input:

using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.EventSystems;

public class SettingsInputButtonController : MonoBehaviour
{
    [HideInInspector] public MyPlayer playerInstance;
    [HideInInspector] public TextMeshProUGUI buttonText;
    public string actionName;
    public int bindingIndex;

    private InputActionRebindingExtensions.RebindingOperation rebindingOperation;

    private void Start()
    {
        ValidateButtonText();
    }

    public void InputButtonPressed()
    {
        // actionName is a public string that matches an input action. For example, "Jump"
        InputAction associatedAction = playerInstance.playerInput.actions.FindAction(actionName);
        EventSystem.current.SetSelectedGameObject(null);
        buttonText.text = "Listening...";
        associatedAction.Disable();
        rebindingOperation = associatedAction.PerformInteractiveRebinding(bindingIndex)
            .OnMatchWaitForAnother(0.1f)
            .OnComplete(cb => {
                rebindingOperation.Dispose();
                ValidateButtonText();
                associatedAction.Enable();
            })
            .Start();

        Debug.Log("Rebinding started for action: " + actionName);
    }

    public void ValidateButtonText()
    {
        InputAction associatedAction = playerInstance.playerInput.actions.FindAction(actionName);
        if (associatedAction != null) {
            buttonText.text = associatedAction.GetBindingDisplayString(bindingIndex);
        }
    }
}

Nothing in this script should prevent my gamepad from sending its input to the rebinding operation. I looked in the Unity rebind example, but it uses a single input user and I did not find anything in the code that would contribute to the issue that I’m currently having. I suspect that I wouldn’t be having any issues if I had a single input user that allowed either controller or keyboard/mouse. All examples that I’ve found for multiple input users don’t have anything on rebinding, so I’m pretty stuck here. If anyone has ideas for a potential solution here, I am open to hearing it!

Finally figured it out - posting it here in case someone else runs into the same issue.

The culprit was bindingindex - apparently binding index not only handles composite binding, but also bindings from different schemes. Super dumb IMO to have them share the same array, but that’s how it’s set up apparently.

In order to fix it, I had to detect when a gamepad is used, and adjust the binding index accordingly.

        if (eggplant.playerInput.currentControlScheme == "Gamepad") {
            bindingIndex = GetGamepadBindingIndex(associatedAction);
        }
    public int GetGamepadBindingIndex(InputAction action)
    {
        for (int i = 0; i < action.bindings.Count; i++) {
            if (action.bindings[i].groups.Contains("Gamepad")) {
                return i;
            }
        }
        return -1;
    }

Once the binding index was corrected, everything worked without any issues.