Unity: Handling Input from Multiple Sources (controllers, keyboards, etc)
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.