Unity: Handling Input from Multiple Sources (controllers, keyboards, etc)

Matt Buckley
Nice Things | iOS + Android Development
2 min readNov 19, 2018

Like this post? You might like BentoBlox too — check out the game here on the App Store.

This week I’m prototyping a game intended to run on multiple platforms. One of the core challenges is anticipating and handling for user input coming from a range of different sources.

My initial approach relies on an Observer-Subscriber model: a singleton UserInputDeviceManager stores a reference to the currently connected input device (a controller, a keyboard, etc), and polls the buttons of that device on Update to determine if any button is in the pressed state:

public class UserInputDeviceManager : Singleton<UserInputDeviceManager>
{
public UserInputDevice currentUserInputDevice; public UserInputDevice[] supportedUserInputDevices = new UserInputDevice[] {
new XBoxOneController(),
new PS3Controller(),
new DualShock4Controller(),
new KeyboardController()
};
override protected void Awake()
{
base.Awake();
SetupCurrentUserInputDevice();
}
private void SetupCurrentUserInputDevice()
{
currentUserInputDevice = System.Array.Find(supportedUserInputDevices, m => m.IsConnected());
}
void Update()
{
currentUserInputDevice.PollButtons();
}
}}

In PollButtons, each UserInputDevice broadcasts an event for any button in the pressed state:

    public void PollButtons()
{
ArrayList buttons = new ArrayList();
buttons.Add(JumpButton);
buttons.Add(ConfirmButton);
buttons.Add(PauseButton);
buttons.Add(DPad.LeftButton);
buttons.Add(DPad.RightButton);
buttons.Add(DPad.TopButton);
buttons.Add(DPad.BottomButton);
foreach (Button button in buttons)
{
if (button.CurrentState == Button.State.Pressed)
{
OnButtonPress(button);
}
}
}

Subscribers can listen for this event, and execute logic accordingly. For example, I have a PlayerMovementController which moves my Player game object based on incoming events from the currently connected device:

    public void HandleButtonPress(Button button)
{
switch (button.action)
{
case UserInputDevice.ButtonName.DPadLeft:
MoveLeft();
break;
case UserInputDevice.ButtonName.DPadRight:
MoveRight();
break;
case UserInputDevice.ButtonName.DPadUp:
Jump();
break;
default:
break;
}
}

This approach is rather homespun; it makes sense and feels good at the moment, but I’m curious to see if it has staying power in this project.

How do you handle user input in your projects? I’d love to hear about alternative approaches from anyone willing to share their thoughts.

Like this post? You might like BentoBlox too — check out the game here on the App Store.

--

--