Custom touch-screen input module

This is an experimental input module that aims to improve the behaviour of Unity UI elements with touch-screen input. If you are experiencing issues with Unity UI-based AC menus on mobile devices, give this a try.

To use it: CustomTouchInputModule.cs: using UnityEngine.EventSystems; using UnityEngine; namespace AC { public class CustomTouchInputModule : StandaloneInputModule { 		private bool allowMouseInput = true; private readonly MouseState m_MouseState = new MouseState ; public bool AllowMouseInput { 			get { 				return allowMouseInput; } 			set { 				allowMouseInput = value; } 		}  		protected void Update { 			AllowMouseInput = !CanDirectlyControlMenus ; } 		protected virtual bool CanDirectlyControlMenus { 			if (KickStarter.settingsManager != null && KickStarter.settingsManager.inputMethod == InputMethod.TouchScreen) { 				return false; } 			if ((KickStarter.stateHandler.gameState == GameState.Paused && KickStarter.menuManager.keyboardControlWhenPaused) ||  				(KickStarter.stateHandler.gameState == GameState.DialogOptions && KickStarter.menuManager.keyboardControlWhenDialogOptions) ||  				(KickStarter.stateHandler.IsInGameplay  && KickStarter.playerInput.canKeyboardControlMenusDuringGameplay)) { 				return true; } 			return false; } 		protected override MouseState GetMousePointerEventData (int id = 0) { 			if (KickStarter.settingsManager == null || KickStarter.settingsManager.inputMethod == InputMethod.MouseAndKeyboard) { 				return base.GetMousePointerEventData (id); } 			if (KickStarter.settingsManager.inputMethod == InputMethod.TouchScreen) { 				return GetTouchEventData (id); } 			PointerEventData leftData; var created = GetPointerData (kMouseLeftId, out leftData, true); leftData.Reset ; Vector2 pos = KickStarter.playerInput.GetMousePosition ; if (created) { 				leftData.position = pos; } 			leftData.delta = pos - leftData.position; leftData.position = pos; leftData.scrollDelta = Input.mouseScrollDelta; leftData.button = PointerEventData.InputButton.Left; eventSystem.RaycastAll (leftData, m_RaycastResultCache); RaycastResult raycast = FindFirstRaycast (m_RaycastResultCache); leftData.pointerCurrentRaycast = raycast; m_RaycastResultCache.Clear ; if (raycast.isValid && KickStarter.menuManager.autoSelectValidRaycasts && !CanDirectlyControlMenus ) { 				KickStarter.playerMenus.EventSystem.SetSelectedGameObject (raycast.gameObject); } 			PointerEventData rightData; GetPointerData (kMouseRightId, out rightData, true); CopyFromTo (leftData, rightData); rightData.button = PointerEventData.InputButton.Right; PointerEventData middleData; GetPointerData (kMouseMiddleId, out middleData, true); CopyFromTo (leftData, middleData); middleData.button = PointerEventData.InputButton.Middle; PointerEventData.FramePressState leftClickState = PointerEventData.FramePressState.NotChanged; if (KickStarter.settingsManager.inputMethod == InputMethod.TouchScreen) { 				if (Input.touchCount == 1) { 					TouchPhase phase = Input.GetTouch (0).phase; switch (phase) { 						case TouchPhase.Began: leftClickState = PointerEventData.FramePressState.Pressed; break; case TouchPhase.Canceled: leftClickState = PointerEventData.FramePressState.Released; break; case TouchPhase.Ended: leftClickState = PointerEventData.FramePressState.PressedAndReleased; break; default: break; } 				}  			}  			else { 				if (KickStarter.playerInput.InputGetButtonDown ("InteractionA")) { 					leftClickState = PointerEventData.FramePressState.Pressed; } 				else if (KickStarter.playerInput.InputGetButtonUp ("InteractionA")) { 					leftClickState = PointerEventData.FramePressState.Released; } 			}  			PointerEventData.FramePressState rightClickState = PointerEventData.FramePressState.NotChanged; if (KickStarter.playerInput.InputGetButtonDown ("InteractionB")) { 				rightClickState = PointerEventData.FramePressState.Pressed; } 			else if (KickStarter.playerInput.InputGetButtonUp ("InteractionB")) { 				rightClickState = PointerEventData.FramePressState.Released; } 			m_MouseState.SetButtonState (PointerEventData.InputButton.Left, leftClickState, leftData); m_MouseState.SetButtonState (PointerEventData.InputButton.Right, rightClickState, rightData); m_MouseState.SetButtonState (PointerEventData.InputButton.Middle, StateForMouseButton (2), middleData); return m_MouseState; } 		private MouseState GetTouchEventData (int id) { 			// Populate the left button...  			PointerEventData leftData; var created = GetPointerData (kMouseLeftId, out leftData, true); leftData.Reset ; if (created) leftData.position = input.mousePosition; //Vector2 pos = input.mousePosition; Vector2 pos = KickStarter.playerInput.GetMousePosition ; if (Cursor.lockState == CursorLockMode.Locked) { 				// We don't want to do ANY cursor-based interaction when the mouse is locked leftData.position = new Vector2 (-1.0f, -1.0f); leftData.delta = Vector2.zero; } 			else { 				leftData.delta = pos - leftData.position; leftData.position = pos; } 			leftData.scrollDelta = input.mouseScrollDelta; leftData.button = PointerEventData.InputButton.Left; eventSystem.RaycastAll (leftData, m_RaycastResultCache); var raycast = FindFirstRaycast (m_RaycastResultCache); leftData.pointerCurrentRaycast = raycast; m_RaycastResultCache.Clear ; // copy the apropriate data into right and middle slots PointerEventData rightData; GetPointerData (kMouseRightId, out rightData, true); CopyFromTo (leftData, rightData); rightData.button = PointerEventData.InputButton.Right; PointerEventData middleData; GetPointerData (kMouseMiddleId, out middleData, true); CopyFromTo (leftData, middleData); middleData.button = PointerEventData.InputButton.Middle; m_MouseState.SetButtonState (PointerEventData.InputButton.Left, StateForMouseButton (0), leftData); m_MouseState.SetButtonState (PointerEventData.InputButton.Right, StateForMouseButton (1), rightData); m_MouseState.SetButtonState (PointerEventData.InputButton.Middle, StateForMouseButton (2), middleData); return m_MouseState; } 		public override void Process { 			bool usedEvent = SendUpdateEventToSelectedObject ; if (eventSystem.sendNavigationEvents) { 				if (!usedEvent) { 					usedEvent |= SendMoveEventToSelectedObject ; } 				if (!usedEvent) { 					SendSubmitEventToSelectedObject ; } 			}  			if (allowMouseInput) { 				ProcessMouseEvent ; } 		}  	}  }
 * 1) Paste the code below into a new C# script named CustomTouchInputModule.cs
 * 2) Attach this script as a component to a new empty GameObject, and make the GameObject a prefab
 * 3) Assign this prefab in to the AC Menu Manager's EventSystem prefab field.