Skip to content

Instantly share code, notes, and snippets.

@codeimpossible
Created November 22, 2017 20:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save codeimpossible/4cd733b8cbd48a420c27033afea165bf to your computer and use it in GitHub Desktop.
Save codeimpossible/4cd733b8cbd48a420c27033afea165bf to your computer and use it in GitHub Desktop.
Cross Platform GamePad Input for Unity

I was getting really fed up with the default input binding system in Unity - specifically around having to map tons of different gamepad Axis and buttons for each platform. It's ridiculous. You end up having to do Application.platform checks all over the place and it's super disgusting.

Anyway, I created an abstraction over some of the input manager. When you call GetAxis it will append the current platform to the axis name. So GetAxis("Horizontal") will map to the HorizontalWINDOWS axis in your input configuration within unity. Unfortunately you still have to map the axis, but it's only Horizontal and Vertical for each platform, so it's not too bad.

The real win here is being able to ask which button BY NAME is being pressed on the gamepad and get a platform specific answer, e.g.

// maps to KeyCode.JoystickButton8 and KeyCode.JoystickButton11 on windows and osx respectively
GetKeyDown(GamePadAbstraction.LEFT_THUMBSTICK); 

To instantiate the input manager, just create a MonoBehaviour that sticks around (i've included a sample of my GameManager.cs file here) and add a public field IInputSystem Input then instantiate it on Awake() with ``` private IInputSystem CreateInputSystem() { switch (Application.platform) { case RuntimePlatform.OSXEditor: case RuntimePlatform.OSXPlayer: return new OsxInputSystem();

    default:
    case RuntimePlatform.WindowsEditor:
    case RuntimePlatform.WindowsPlayer:
        return new WindowsInputSystem();
}

}```

using System;
using UnityEngine;
public class GameManager : MonoBehaviour {
public IInputSystem Input;
public static GameManager Instance;
void Awake() {
if (Instance == null)
{
DontDestroyOnLoad(gameObject);
Input = CreateInputSystem();
Instance = this;
}
else if (Instance != this)
{
DestroyObject(gameObject);
}
}
public PlayerInputState GetPlayerInputState()
{
return Input.GetInputState();
}
private IInputSystem CreateInputSystem()
{
switch (Application.platform)
{
case RuntimePlatform.OSXEditor:
case RuntimePlatform.OSXPlayer:
return new OsxInputSystem();
default:
case RuntimePlatform.WindowsEditor:
case RuntimePlatform.WindowsPlayer:
return new WindowsInputSystem();
}
}
}
using UnityEngine;
public interface IInputSystem
{
PlayerInputState GetInputState();
}
public abstract class InputSystemBase
{
protected abstract string PlatformSuffix { get; }
public PlayerInputState GetInputState()
{
return new PlayerInputState()
{
WantsToMoveRight = GetKey(KeyCode.RightArrow) || GetAxis("Horizontal") > 0,
WantsToMoveLeft = GetKey(KeyCode.LeftArrow) || GetAxis("Horizontal") < 0,
WantsToJump = false,
ToggleSneak = GetKeyDown(KeyCode.C) || GetKeyDown(GamePadAbstraction.LEFT_THUMBSTICK),
ShouldRun = GetKey(KeyCode.LeftShift) || GetKey(GamePadAbstraction.LEFT_BUMPER),
WantsToShoot = false, //Input.GetAxis("RightTrigger") != 0f,
DrawingGun = false, //Input.GetAxis("LeftTrigger") != 0f,
};
}
private float GetAxis(string commonName)
{
return Input.GetAxis(GetPlatformInputName(commonName));
}
private bool GetKeyDown(KeyCode key)
{
return Input.GetKeyDown(key);
}
private bool GetKey(KeyCode key)
{
return Input.GetKey(key);
}
private bool GetKey(GamePadAbstraction key)
{
return Input.GetKey(GetPlatformGamePadButton(key));
}
private bool GetKeyDown(GamePadAbstraction key)
{
return Input.GetKeyDown(GetPlatformGamePadButton(key));
}
private string GetPlatformInputName(string commonName)
{
return commonName + PlatformSuffix;
}
protected abstract KeyCode GetPlatformGamePadButton(GamePadAbstraction button);
}
public enum GamePadAbstraction
{
X,
Y,
B,
A,
RIGHT_BUMPER,
LEFT_BUMPER,
RIGHT_THUMBSTICK,
LEFT_THUMBSTICK,
START,
BACK,
}
using System;
using UnityEngine;
public class OsxInputSystem : InputSystemBase, IInputSystem
{
protected override string PlatformSuffix
{
get
{
return "OSX";
}
}
protected override KeyCode GetPlatformGamePadButton(GamePadAbstraction button)
{
switch (button)
{
case GamePadAbstraction.RIGHT_BUMPER: return KeyCode.JoystickButton13;
case GamePadAbstraction.LEFT_BUMPER: return KeyCode.JoystickButton14;
case GamePadAbstraction.LEFT_THUMBSTICK: return KeyCode.JoystickButton11;
case GamePadAbstraction.RIGHT_THUMBSTICK: return KeyCode.JoystickButton12;
case GamePadAbstraction.BACK: return KeyCode.JoystickButton10;
case GamePadAbstraction.START: return KeyCode.JoystickButton9;
case GamePadAbstraction.Y: return KeyCode.JoystickButton19;
case GamePadAbstraction.B: return KeyCode.JoystickButton17;
case GamePadAbstraction.A: return KeyCode.JoystickButton16;
case GamePadAbstraction.X: return KeyCode.JoystickButton18;
}
return KeyCode.None;
}
}
using System;
using UnityEngine;
public class WindowsInputSystem : InputSystemBase, IInputSystem
{
protected override string PlatformSuffix
{
get
{
return "WINDOWS";
}
}
protected override KeyCode GetPlatformGamePadButton(GamePadAbstraction button)
{
switch(button)
{
case GamePadAbstraction.RIGHT_BUMPER: return KeyCode.JoystickButton4;
case GamePadAbstraction.LEFT_BUMPER: return KeyCode.JoystickButton5;
case GamePadAbstraction.LEFT_THUMBSTICK: return KeyCode.JoystickButton8;
case GamePadAbstraction.RIGHT_THUMBSTICK: return KeyCode.JoystickButton9;
case GamePadAbstraction.BACK: return KeyCode.JoystickButton6;
case GamePadAbstraction.START: return KeyCode.JoystickButton7;
case GamePadAbstraction.Y: return KeyCode.JoystickButton3;
case GamePadAbstraction.B: return KeyCode.JoystickButton1;
case GamePadAbstraction.A: return KeyCode.JoystickButton0;
case GamePadAbstraction.X: return KeyCode.JoystickButton2;
}
return KeyCode.None;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment