[Official] Input System Improvements

Hi all,

The Input system needs some Unity love. This one is in many ways simpler than other systems, but it’s always good to make sure we have though through the use-cases. We also need to think about the scope in how far we go with it.

Is it better to have a simple, modular system with an API you use to roll-your-own way of supporting different input controllers, platforms and bindings? Or are you more concerned with how multiple systems work together on one platform? Or multiple platforms supported in one code path? Or? Of course the answer is “we want it all, now!”…

You get the idea; we would love to collect some use-cases we might not though of, and what troubles you the most when supporting input on the huge array of platforms we support.

Thanks!
Brett

Multiple systems work toghter on one platform and modular at the same time. Think of a desktop game and how many type of controllers one can plugin. The main problem on this is with axis, so would need some system in place where you can define a “batch” of each controller you can support, so you can just interface to the inputs that particular controller needs.

Also events to detect if you are using mouse wheel for example for key binding (think of a switch weapon system in a fps). Surely it can be already done in many ways, but is kinda hacky at the moment.

Just for the hell of it, I’ll post my convulted key binding system:

using UnityEngine;
using System.Collections.Generic;

[AddComponentMenu("")]
public class NMInput : MonoBehaviour {

	static private bool isInitialized;
	static private List<string> kName = new List<string>();                               //Key input nome
	static private List<KeyCode> kPrimary = new List<KeyCode>();                          //Key input primario
	static private List<KeyCode> kSecondary = new List<KeyCode>();                        //Key input secondario

	static private List<string> aName = new List<string>();                               //Axis nomi stringhe	
	static public List<NMAxisInput> axis = new List<NMAxisInput>();                       //Axis lista classe
	static private int aIndex = 0;                                                        //Indice per riferimento veloce agli assi

	static private float aSensitivity = 3;                                                //Sensività asse predefinita
	static private float aGravity = 3;                                                    //Gravità asse predefinita

	#region INPUT_FUNCTIONS

	//Crea istanza se necessario
	public static void Init() {NMInputInit();}

	//Crea istanza
	private static void NMInputInit() {
		if (!isInitialized) {
			GameObject o;

			if (GameObject.Find("NMInput")) 
				o = GameObject.Find("NMInput");
			else 
				o = new GameObject("NMInput");

			if(GameObject.Find ("NMSystem"))
				o.transform.parent = GameObject.Find ("NMSystem").transform;

			if (!o.GetComponent<NMInput>())
				o.AddComponent<NMInput>();

			isInitialized = true;
		}
	}

	//Controlla se questa istanza esiste
	static public bool Exist() {return isInitialized; }

	//Ritorna tasto rilasciato
	static public bool GetKeyUp (string k) {
		if (Input.GetKeyUp(kPrimary[kName.IndexOf(k)]) || Input.GetKeyUp(kSecondary[kName.IndexOf(k)]))
			return true;	
		else
			return false;
	}

	//Ritorna tasto premuto
	static public bool GetKeyDown (string k) {
		if (Input.GetKeyDown(kPrimary[kName.IndexOf(k)]) || Input.GetKeyDown(kSecondary[kName.IndexOf(k)]))
			return true;	
		else
			return false;
	}

	//Ritorna tasto tenuto premuto
	static public bool GetKey (string k) {
		if (Input.GetKey(kPrimary[kName.IndexOf(k)]) || Input.GetKey(kSecondary[kName.IndexOf(k)]))
			return true;	
		else
			return false;
	}

	//Ritorna valore asse
	static public float GetAxis (string a) {
		int index = 0;

		for (int i = 0; i < aName.Count; i++)
			if (axis [i].aName == a)
				index = i;

		return axis [index].GetAxisInput (a);
	}

	//Setta key input
	static public void SetKeyInput (string k, KeyCode p, KeyCode s) {NMInputInit(); kName.Add (k); kPrimary.Add (p); kSecondary.Add (s);}

	//Setta asse con sensività e gravitò predefinite
	static public void SetAxisInput (string a, string p, string n) {
		NMInputInit();
		aName.Add (a);
		axis.Add (new NMAxisInput());
		axis[aIndex].SetAxisInput(a, GetKeyPrimary(p), GetKeySecondary(p), GetKeyPrimary(n), GetKeySecondary(n), aSensitivity, aGravity);
		aIndex++;
	}

	//Setta asse con sensività e gravità specifiche
	static public void SetAxisInput (string a, string p, string n, float s, float g) {
		NMInputInit();
		aName.Add (a);
		axis.Add (new NMAxisInput());
		axis[aIndex].SetAxisInput(a, GetKeyPrimary(p), GetKeySecondary(p), GetKeyPrimary(n), GetKeySecondary(n), s, g);
		aIndex++;
	}

	//Controlla key input nel dizionario (primario)
	static private KeyCode GetKeyPrimary (string c) {
		KeyCode v = KeyCode.None;
	
		if (kName.Contains(c))
			v = kPrimary[kName.IndexOf(c)];

		return v;
	}

	//Controlla key input nel dizionario (secondario)
	static private KeyCode GetKeySecondary (string c) {
		KeyCode v = KeyCode.None;

		if (kName.Contains(c))
			v = kSecondary[kName.IndexOf(c)];

		return v;
	}
	
	//Ritorna l'indice dell'asse dal nome
	static private int GetAxisIndex (string n) {
		int a = 0;
		
		for(int i = 0; i < aName.Count;i++) 
			if(aName[i].Contains(n))
				a = i;
		
		return a;
	}

	#endregion

	//Classe specifica per gli assi
	[System.Serializable]
	public class NMAxisInput {
		public string aName;                //Nome asse
		public float positive;              //Magnitudine positivo
		public float negative;              //Magnitudine negativo
		public float magnitude;             //Magnitudine corrente

		public float gravity = 3;           //Gravità                                                    
		public float sensitivity = 3;       //Sensività

		private KeyCode posPrimaryKey;      //Primario positivo key input
		private KeyCode posSecondaryKey;    //Secondario positivo key input
		private KeyCode negPrimaryKey;      //Primario negativo key input
		private KeyCode negSecondaryKey;    //Secondario negativo key input

		private bool posInput;              //Se key input primario-secondario positivo sono premute
		private bool negInput;              //Se key input primario-secondario negativo sono premute
		private bool posPrimaryInput;       //Key input positivo primario premuto
		private bool posSecondaryInput;     //Key input positivo secondario premuto
		private bool negPrimaryInput;       //Key input positivo negativo premuto
		private bool negSecondaryInput;     //Key input positivo negativo premuto

		//Setta asse predefinito
		public void SetAxisInput (string n, KeyCode p1, KeyCode p2, KeyCode n1, KeyCode n2, float s, float g) {
			aName = n;
			posPrimaryKey = p1; posSecondaryKey = p2;
			negPrimaryKey = n1; negSecondaryKey = n2;
			sensitivity = s;
			gravity = g;
		}

		//Ritorna la magniudine dell'asse
		public float GetAxisInput (string a) {
			if(aName == a) {
				if(Input.GetKey(posPrimaryKey) || Input.GetKey(posSecondaryKey)) {
					posPrimaryInput = Input.GetKey(posPrimaryKey);
					posSecondaryInput = Input.GetKey(posSecondaryKey);

					if (posPrimaryInput || posSecondaryInput)
						posInput = true;
					else
						posInput = false;

					return GetPositiveAxis();
				}
				else if (Input.GetKey(negPrimaryKey) || Input.GetKey(negSecondaryKey)) { 
					negPrimaryInput = Input.GetKey(negPrimaryKey);
					negSecondaryInput = Input.GetKey(negSecondaryKey);

					if (negPrimaryInput || negSecondaryInput)
						negInput = true;
					else
						negInput = false;

					return GetNegativeAxis();
				}
				else
				{
					posInput = negInput = false;
					return GetGravityAxis();
				}
			}
			else
			{
				return 0;
			}
		}

		//Ritorna la magnitudine positiva dell'asse
		float GetPositiveAxis () {
			if (posInput) {
				positive += sensitivity * Time.deltaTime;
					
				if(positive > 1) 
					positive = 1;
					
				magnitude = positive;
			}
			return magnitude;
		}

		//Ritorna la magnitudine negativa dell'asse
		float GetNegativeAxis () {
			if (negInput){	
				negative -= sensitivity * Time.deltaTime;
				
				if(negative < -1) 
					negative = -1;
				
				magnitude = negative;
			}
			return magnitude;
		}

		//Se nulla è premuto itorna la magnitudine a 0
		float GetGravityAxis () {
			if (magnitude < 0) {
				negative += gravity * Time.deltaTime;

				if(negative > 0) 
					negative = 0;
				
				magnitude = negative;
			}

			if (magnitude > 0) {
				positive -= gravity * Time.deltaTime;

				if(positive < 0) 
					positive = 0;
			
				magnitude = positive;
			}
			return magnitude;
		}
	}
}

What i miss from the Input current system: simulate input.

i would like to be able to do something like call “Input.Simulate.getKey(Keycode.Space)” in a function
then all my if(Input.GetKey(Keycode.Space) will return true

1 Like

I love the fact that, with the current input system, I can call GetAxis and get platform independent results. What I don’t love is that I can’t modify those axes at runtime. We need access to the settings, if only to allow players to change input setups in-game, eithout having to exit, change settings, and then restart. Script access to key definitions is crucial.

1 Like

I would like the event input system to pick up right shift and alt gr.

Framerate-independent input. http://feedback.unity3d.com/suggestions/realtime-input-framerate-indepe

Basically even if you have a shitty framerate that’s going all over the place INPUT SHOULD NOT BE AFFECTED, EVER.

5 Likes

Make it changable from the API.
Almost every game uses key changes ingame in its own menu instead of unitys I-will-show-you-the-input-manager-first.

I don’t know if the inputs are usable before I played the game, so I have to start the game, try it, quit the game, start a new one, change a key, play it, quit it… Other than that, it is enough for me.

I don’t know how to use several controllers in one game, but I am not affected by it.

I agree to part of the above points:

  • Please make the input assignements runtime changeable so we can use it with options menus, external config files etc. Nothing against the startup window, but calling its look and lack of any configurability make it an absolute no go
  • Add the capability to simulate input or raise input events in general (usefull for Unit Testing and mapping other input devices without OS level event raising - we did that for TUIO and Joysticks and its definitely no fun just to get the UI to respond …)
  • Add the capability to the input system to globally ignore / disable specific hotkey combos so games can decide to ignore the windows key and alt-tab altogether for example

That would be cool, it would make touch screen input much more easy to implement!

I guess we have two groups here. The one like me loves it superbabyeasy. Cannot be easy enough. The others loves to have full control over everything. It’s hard to put this under one hat. I fear you will need two solutions here. One super easy solution at the surface, and a advanced solution in an advanced setup.

Suggestion for the input manager in the project settings: i was always at heavy hunting what term can be used in the edit boxes. Is it escape, Escape, esc, Esc? This issue becomes even more interesting with the not so common letters like the f buttons, or the normal values vs the numpad values. And of course for the joypad. What button is what. And then there is the american qwerty keyboard and the european qwertz keyboard. Happy guessing. American keyobard does not have umlauts.

What about a “Please press key” feature, like in the hotkey manager of Blender? No more hunting anymore what comes into the edit box …

TL;DR:

  • COMPLETE script access to input manager. Editor and Runtime.
  • Simulated input events
  • Better location/mapping of connected devices (multiple joysticks, mouses, etc.)

Please and thank you :slight_smile:

Make official input templates for iOS joystick, Android Bluetooth Joystick, Ouya, PS3 joystick, XBOX joystick.

Right now, I have to code dozens of input entries for each joystick.

Aggregation system.

Each monobehavior has an Update() which checks Input.Key or Input.Touch.

Make it such that one monobehavior, for the whole scene, is able to check for Input and delegate it to the rest of the GUI, Character Controller, NPC controller, etc.

@UT

Just integrate this :

http://forum.unity3d.com/threads/238109-jInput_Mapping-support-amp-feedback

BTW, have you planed an ‘[Official] Mecanim System Improvements’ thread? :smile:

Why jInput and not cInput?

Because i love the simplicity and the demo webplayer works well with ALL joystick/joypad i tried. This is not the case of cInput. I bought it, but i plan to take jInput this week.

Totally agree as well!!

The fact that there’s no way to natively change inputs at runtime is absolutely ridiculous for a game engine made after 1996. On top of that, there should be an input detection system, both that can be called in scripts and in the main editor for setup, that allows the user to press a key to set up an input.

  • We need to be able to read and write to it from scripting. It’s hard to set up the Keys and their behavior in the Inspector and impossible to do from scripting. To achieve in-game control menu I ended up using cInput, which is an amazing asset, but it’s impossible to do out of the box without a major effort as far as the normal Input Manager is concerned.

  • Vibration support! It’s such a bummer that it is missing.

  • Simplified settings. I don’t actually need to set gravity and sensitivity over and over again, I only need it once. I can do this with cInput, so in my Initialize function I have something like cInput.sensitivity = 3f * Managers.Settings.userSensitivity; - so simplify it, but still offer these individual settings as optional for those that need them.

  • Better support for common Gamepads. You need to guess which Keycode responds to what button on the pad. I ended up having to do a cheatsheet for the 360 pad through trial-by-error. The KeyCode class is nice, but for pads the variables are far too ambiguous. Even for keyboard and mouse they sometimes are. But primarily for gamepads I’d like to see naming representative of the buttons on the pad, considering how the 360 gamepad in particular is a PC standard. Or, at the very least, provide a official cheatsheet so we don’t have to make one of our own or google for one (Users be aware many of the google results are outdated, at least at the time I made my cheatsheet). We could write our own scripts to help with that, but it’s still annoying.

That would be easy enough to implement if they give you access to the actions at runtime. I am doing it already with Rebind however getting input in the editor is not very accurate.