Unity Input Manager pain has lasted for years. On the Unity feedback site you can find requests for InputManager programmatic access dating from 2009.
Futile!
Problems:
1) Ingame input controller mapping.
Unity has a user interface for mapping predefined bindings at the start the of game. Changing mappings later requires a game restart.
2) Handling input in code based on states/tags abstracting real input.
Some sort of abstraction is done thru InputManager's well known "Horizontal" and "Vertical", but that abstraction is still bonded to axis and buttons of the developer's test controller and not based on Actions/Final States of the game (for ex. Mecanima Animation States) mapped to player's currently plugged-in controller.
3) Saving and restoring user preferences (Input settings)
Unity's built-in PlayerPref might do the trick if you do not plan to support Web, Droid... and if file size is not bigger then 1 megabyte. Though XML I think is a better solution as it is human readable and also exchangable between systems and players.
4) Distinct positive and negative part of the axis.
Unity will recognize controller's axis as one part and gives value -1 to 1 to -1. It is expected values to be in range of 1 to 0 to -1, so distinction of, for example turning left/right on wheel input controller or joystick's push/pull forward/backward, is possible.
5) OS independent driver and easy expansion with drivers supporting other devices and special properties
Unity's internal handler might not recognize HID device or it would identify same button in different system differently. Also doesn't offer support of device extra features like force feedback, IR cameras, accelerators, gyros ... today more and more parts of modern input controllers. Instead of plug and play OS dependent drivers, a much better solution seems to be OS dependent HID interfaces with OS independent pluggable drivers.
6) Handling input axis and buttons as digital or analog
In Unity thru Input class you can handle axis only as analog and buttons as analog/digital. It's handy to have axis as digital events HOLD, DOWN, UP...
7) Create combination of inputs that would trigger action/state
Unity doesn't offer an out of the box way for combined input action like 2 keys in row, axis move and button push...for example in fighting game scenario -> 2times joystick left + fire (Mustafa kick from Capcoms Cadillacs and Dinosaurs)
8) Handling inputs by events
Seems the whole Unity engine is not much planned as event-based, signal or reaction based system and encouraging use of Broadcast messaging and handling complex input inside Update is far from a good solution even if you need last processor's MIPS.
9) Plug and play instead of plug and pray.
Attach or remove controllers while game is running and continue playing.
10) Profiles - Layouts
Why not InControl or CInput?
Both are based on the bad foundation which is Unity InputManager and even they give you runtime mapping and change, they have same sickness even worse. They create InputManager.asset with all possible Joystick#+Buttons# (Joystick1Button1,...Joystick2Button2...) combinations and by reading name of joystick they give you contoroller layout(profile), claming they support bunch of devices. Actually they didn't support anything else then what Unity default driver support(on button-axis level),... so NO AXIS DIRECTION DISTINNCTION, NO PLUG and PLAY, NO FFD or SPECIAL FEATURES ACCELEROMETERS, GYROS, IR CAM...., NO COMBOS, NO EXPANSION SUPPORT...AND NOT FREE
1) Ingame input controller mapping.
Input Mapper allows you to easily map game controller input to Animation States from your Animation Controller or custom states
2) Handling input in code based on states/tag abstracting real input.
InputMapper API is very similar to Unity APIs with the big difference that it is abstraction on two levels. First you do not program with real inputs like KeyCode.Q or Joystick1Button99, but with states which also allows player to map different input to same action state.
3) Saving and restoring user preferences
Saving would export your settings to .xml file and States.cs will be generated containing enum of your mapped states.
Now you can forget about:
as we are taught in Unity tutorials, but you can use States.[some state].
Library contains a simple component so you can test user perspective right away. Just drag saved .xml and Play.
4) Distinct positive and negative part of the axis.
System recongizes Left,Right,Forward,Backward on POV axis and Positive/Negative on axis.
5) OS independent driver and easy expansion with drivers supporting other devices and special properties
I understood Unity couldn't support all game devices but some system that allows simple binding of driver might be a good idea (Yeah they have plugins.....).
So instead of building plugins for all OSes InputMapper system had built HID interface systems for (Win,Web,Droid and OS(not tested)) that allows writing only one device specified driver OS in independent.
Device would be handled by default driver (WinMMDriver for Win and OSXDriver for OSX) or by custom driver if added like:
Your implementation of custom device driver needs to handle two entry points:
Resolve device where HIDInterface provide device info from the OS, you can check VID and PID to decide to handle and init device properties and structures, or not returning null, and Update function to query device by use of provided Read/Write methods and fill the JoystickDevice structures, so they can be accessed by InputManager. Scared about handling few bytes??? :) check XInputDriver.cs.
Still want to use Unity InputManger as backup???
Swap your InputManger.asset with InputManager.asset from github source code.
6) Handling input axis and buttons as digital or analog
Second abstraction is that you can use digital or analog output regardless of whether your real input source is digital or analog meaning for ex. Joystick Axis is counted as analog can produce normalized values from 0 to 1 but also pushed true/false, or key or even mouse button.
7) Create combination of inputs that would trigger action/state
By just clicking keys/mouse/buttons or moving joystick, as SINGLE, DOUBLE and LONG. Primary and secondary. In the example below I've mapped Wave state combo of Mouse1 double clicks + Joystick1AxisYForward (Long push forward of the Joystick) + double click of letter Y.
You can set modifier format or clicks sensitivity.
8) Handling inputs by events
As the Update method gets overcrowded the library offers modern input handling solution by use of Event based system.
Hardcore developers can manually map input to states and even mix with loaded settings.
In KeyCodeExtension all KeyCode stuff are supported plus additional for Joystick Axis mapping.
9) Plug and play instead of plug and pray.
Attach or remove/switch controllers while game is running, remap inputs and continue playing.
10) Profiles - Layouts
Your homework.
Devices used during testing: XBox360W controller, ThrustMaster Wheel FFD, Wiimote + Nunchuk.
One classic Gamepad controller, one Wheel and complex controller.
19.08.14 Thrustmaster wheel RGT FFD demo WIN+DROID
GITHUB: https://github.com/winalex/Unity3d-InputMapper
Code is free if you contribute by solving a bug or enhance some version.!!!Joking :) Who can stop you/us.
Feedback, Forks are welcome if you aren't too smart, too movie star or too busy making money.
Gmail me as winxalex.
Knowledge should be free!
13.07.2014 Added WiimoteDevice and WiimoteDriver Skeleton
22.07.2014 Quite more stability and plug in/out supported added.
26.07.2014 Web Player joystick support (Chrome, FireFox)
01.10.2014 WiiDevice and WiiDriver
05.10.2014 XInput driver pure C# (No DirectX xinput.dll wrappers)
13.10.2014 (OSXDriver default driver pure C#)
17.10.2014 (Thrustmaster Wheel FFD and XBOX360W working on OSX)
CONCEPT PROVED!!!
Futile!
Problems:
1) Ingame input controller mapping.
Unity has a user interface for mapping predefined bindings at the start the of game. Changing mappings later requires a game restart.
2) Handling input in code based on states/tags abstracting real input.
Some sort of abstraction is done thru InputManager's well known "Horizontal" and "Vertical", but that abstraction is still bonded to axis and buttons of the developer's test controller and not based on Actions/Final States of the game (for ex. Mecanima Animation States) mapped to player's currently plugged-in controller.
3) Saving and restoring user preferences (Input settings)
Unity's built-in PlayerPref might do the trick if you do not plan to support Web, Droid... and if file size is not bigger then 1 megabyte. Though XML I think is a better solution as it is human readable and also exchangable between systems and players.
4) Distinct positive and negative part of the axis.
Unity will recognize controller's axis as one part and gives value -1 to 1 to -1. It is expected values to be in range of 1 to 0 to -1, so distinction of, for example turning left/right on wheel input controller or joystick's push/pull forward/backward, is possible.
5) OS independent driver and easy expansion with drivers supporting other devices and special properties
Unity's internal handler might not recognize HID device or it would identify same button in different system differently. Also doesn't offer support of device extra features like force feedback, IR cameras, accelerators, gyros ... today more and more parts of modern input controllers. Instead of plug and play OS dependent drivers, a much better solution seems to be OS dependent HID interfaces with OS independent pluggable drivers.
6) Handling input axis and buttons as digital or analog
In Unity thru Input class you can handle axis only as analog and buttons as analog/digital. It's handy to have axis as digital events HOLD, DOWN, UP...
7) Create combination of inputs that would trigger action/state
Unity doesn't offer an out of the box way for combined input action like 2 keys in row, axis move and button push...for example in fighting game scenario -> 2times joystick left + fire (Mustafa kick from Capcoms Cadillacs and Dinosaurs)
8) Handling inputs by events
Seems the whole Unity engine is not much planned as event-based, signal or reaction based system and encouraging use of Broadcast messaging and handling complex input inside Update is far from a good solution even if you need last processor's MIPS.
9) Plug and play instead of plug and pray.
Attach or remove controllers while game is running and continue playing.
10) Profiles - Layouts
Why not InControl or CInput?
Both are based on the bad foundation which is Unity InputManager and even they give you runtime mapping and change, they have same sickness even worse. They create InputManager.asset with all possible Joystick#+Buttons# (Joystick1Button1,...Joystick2Button2...) combinations and by reading name of joystick they give you contoroller layout(profile), claming they support bunch of devices. Actually they didn't support anything else then what Unity default driver support(on button-axis level),... so NO AXIS DIRECTION DISTINNCTION, NO PLUG and PLAY, NO FFD or SPECIAL FEATURES ACCELEROMETERS, GYROS, IR CAM...., NO COMBOS, NO EXPANSION SUPPORT...AND NOT FREE
Input Mapper system to try addressing above issues
1) Ingame input controller mapping.
Input Mapper allows you to easily map game controller input to Animation States from your Animation Controller or custom states
2) Handling input in code based on states/tag abstracting real input.
InputMapper API is very similar to Unity APIs with the big difference that it is abstraction on two levels. First you do not program with real inputs like KeyCode.Q or Joystick1Button99, but with states which also allows player to map different input to same action state.
if(InputManager.GetInputDown((int)States.Wave)){ Debug.Log("Wave Down"); }
3) Saving and restoring user preferences
Saving would export your settings to .xml file and States.cs will be generated containing enum of your mapped states.
public enum States:int{ Wave=1397315813, MyCustomState=-1624475888,
Now you can forget about:
// static int idleState = Animator.StringToHash("Base Layer.Idle"); // static int locoState = Animator.StringToHash("Base Layer.Locomotion");
as we are taught in Unity tutorials, but you can use States.[some state].
Library contains a simple component so you can test user perspective right away. Just drag saved .xml and Play.
4) Distinct positive and negative part of the axis.
System recongizes Left,Right,Forward,Backward on POV axis and Positive/Negative on axis.
5) OS independent driver and easy expansion with drivers supporting other devices and special properties
I understood Unity couldn't support all game devices but some system that allows simple binding of driver might be a good idea (Yeah they have plugins.....).
So instead of building plugins for all OSes InputMapper system had built HID interface systems for (Win,Web,Droid and OS(not tested)) that allows writing only one device specified driver OS in independent.
Device would be handled by default driver (WinMMDriver for Win and OSXDriver for OSX) or by custom driver if added like:
//supporting devices with custom drivers InputManager.AddDriver(new XInputDriver());
Your implementation of custom device driver needs to handle two entry points:
(1)public IJoystickDevice ResolveDevice(IHIDDeviceInfo info)... (2)public void Update(IJoystickDevice joystick)...
Resolve device where HIDInterface provide device info from the OS, you can check VID and PID to decide to handle and init device properties and structures, or not returning null, and Update function to query device by use of provided Read/Write methods and fill the JoystickDevice structures, so they can be accessed by InputManager. Scared about handling few bytes??? :) check XInputDriver.cs.
Still want to use Unity InputManger as backup???
public enum States:int{ InputManager.AddDriver(new UnityDriver());//(-1 to 1 to -1)
Swap your InputManger.asset with InputManager.asset from github source code.
6) Handling input axis and buttons as digital or analog
Second abstraction is that you can use digital or analog output regardless of whether your real input source is digital or analog meaning for ex. Joystick Axis is counted as analog can produce normalized values from 0 to 1 but also pushed true/false, or key or even mouse button.
//using input as digital bool bHold=(InputManager.GetInput((int)States.Walk_Forward,false)); //using input as analog value float analogValue=InputManager.GetInput((int)States.Walk_Forward,false,0.3f,0.1f,0f);
7) Create combination of inputs that would trigger action/state
By just clicking keys/mouse/buttons or moving joystick, as SINGLE, DOUBLE and LONG. Primary and secondary. In the example below I've mapped Wave state combo of Mouse1 double clicks + Joystick1AxisYForward (Long push forward of the Joystick) + double click of letter Y.
You can set modifier format or clicks sensitivity.
8) Handling inputs by events
As the Update method gets overcrowded the library offers modern input handling solution by use of Event based system.
//Event Based input handling InputEvent ev = new InputEvent("Click_W+C_State"); //InputEvent ev = new InputEvent((int)States.SomeState); ev.CONT+=new EventHandler(Handle1); ev.CONT+= new EventHandler(Handle2); ev.UP += new EventHandler(onUp);//this wouldn't fire for combo inputs(single only) ev.DOWN += new EventHandler(onDown);//this wouldn't fire for combo inputs(single only) void onUp(object o, EventArgs args) { Debug.Log("Up"); } void onDown(object o, EventArgs args) { Debug.Log("Down"); } void Handle1(object o, EventArgs args) { Debug.Log("Handle1"); } void Handle2(object o, EventArgs args) { Debug.Log("Handle2"); }
Hardcore developers can manually map input to states and even mix with loaded settings.
InputManager.loadSettings(Path.Combine(Application.streamingAssetsPath,"InputSettings.xml")); //adding input-states pairs manually InputManager.MapStateToInput("My State1",new InputCombination("Mouse1+Joystick12AxisXPositive(x2)+B")); InputManager.MapStateToInput("Click_W+C_State", KeyCodeExtension.Alpha0.DOUBLE,KeyCodeExtension.JoystickAxisPovYPositive.SINGLE);
In KeyCodeExtension all KeyCode stuff are supported plus additional for Joystick Axis mapping.
9) Plug and play instead of plug and pray.
Attach or remove/switch controllers while game is running, remap inputs and continue playing.
10) Profiles - Layouts
Your homework.
Devices used during testing: XBox360W controller, ThrustMaster Wheel FFD, Wiimote + Nunchuk.
One classic Gamepad controller, one Wheel and complex controller.
19.08.14 Thrustmaster wheel RGT FFD demo WIN+DROID
GITHUB: https://github.com/winalex/Unity3d-InputMapper
Code is free if you contribute by solving a bug or enhance some version.!!!Joking :) Who can stop you/us.
Feedback, Forks are welcome if you aren't too smart, too movie star or too busy making money.
Gmail me as winxalex.
Knowledge should be free!
13.07.2014 Added WiimoteDevice and WiimoteDriver Skeleton
22.07.2014 Quite more stability and plug in/out supported added.
26.07.2014 Web Player joystick support (Chrome, FireFox)
01.10.2014 WiiDevice and WiiDriver
05.10.2014 XInput driver pure C# (No DirectX xinput.dll wrappers)
13.10.2014 (OSXDriver default driver pure C#)
17.10.2014 (Thrustmaster Wheel FFD and XBOX360W working on OSX)
CONCEPT PROVED!!!