Ultimate Input Manager for Unity

Published October 30, 2014 by Alex Winx, posted by winxalex
Do you see issues with this article? Let us know.
Advertisement
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

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"); } if(InputManager.GetInputUp((int)States.MyCustomState)){ Debug.Log(States.MyCustomState + "-Up"); // animator.Play((int)States.Wave); } 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. Clipboard02.jpg 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) that allows writing only one device specific driver - OS 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)... ResolveDevice 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. Originally OS implementation of ResolveDevice point is by using Report HID Page from device description, but that restrict using devices that aren't planned to work with that OS, like Wiimote,Xbox Gamepad... In Input Mapper you need simply to extend JoystickDevice Class, which already contains some basic functionality supporting axes and buttons, by adding specialized properties of device you are planning to support. Update point is synchronization point with Unity. System use high level synch and async ReadXXX methods and return buffered byte array. What each of bytes means is easy to decipher as there are many web sites about any devices. Developer task is to fill JoystickDevice structure with values processed from byte array returned. Write methods are used for setup the device...like light leds, start FFD, enable disable.... Still want to use Unity InputManger as backup??? 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(similar to Input.GetKey) bool bHold=(InputManager.GetInput((int)States.Walk_Forward,false)); //using input as analog value(similar to Input.GetAxis) 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. //atOnce (default=false) //Function returns true when combination pressed in row, If atOnce set to true, function return true //when all keys/buttons in combination are pressed. bool bCombo = InputManager.GetInput((int)States.Click_W+C_State, atOnce); You can set modifier format or clicks sensitivity. Clipboard01.jpg 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!!!
Cancel Save
0 Likes 0 Comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!

Ultimate Unity Input Manager. Tame the controllers diversity beast. Minimal code that supports even devices that aren't planned to work on designated systems

Advertisement

Other Tutorials by winxalex

winxalex has not posted any other tutorials. Encourage them to write more!
Advertisement