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:
- Paste the code below into a new C# script named CustomTouchInputModule.cs
- Attach this script as a component to a new empty GameObject, and make the GameObject a prefab
- Assign this prefab in to the AC Menu Manager's EventSystem prefab field.
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 ();
}
}
}
}