- Home /
Unity UI - Mouse Clicks Clearing Selected Object in Eventsystem
Hi,
I was wondering if anyone knows of a method to prevent mouse clicks deselecting objects in a scene when the click doesnt hit a UI element.
When I select a UI element and then click into the empty space next to it, the currently selected object becomes deselected.
Any advice on how to prevent this would be appreciated.
Cheers,
John
Similar problem here, I want to navigate through the UI by only using the keyboard. However, because the mouse click is being detected (mouse is hidden and locked) the first selected object (button) becomes unselected and it results in me not being able to navigate niether with mouse nor keyboard.
Answer by IsaiahKelly · Feb 19, 2016 at 03:36 PM
You need to create your own custom Input Module to change this behavior.
Create a new C# script and name it "MyInputModule".
Copy & paste the StandaloneInputModule source code into this new script and replace all occurrences of "StandaloneInputModule" with "MyInputModule" in the newly copied code.
To stop mouse clicks from deselecting objects, just delete or comment-out line 322 in the new script:
DeselectIfSelectionChanged(currentOverGo, pointerEvent);
Or to disable pointer input completely, just delete or comment-out line 179 in the new script:
ProcessMouseEvent();
Finally, remove the StandaloneInputModule script attached to the EventSystem object and replace it with your new MyInputModule script to use it.
Thanks, this worked great.
In my case I still wanted objects to be deselected if there was a left click on nothing so I changed line 322 to:
if (data.buttonData.button == PointerEventData.InputButton.Left && !EventSystem.current.IsPointerOverGameObject()) {
DeselectIfSelectionChanged(currentOverGo, pointerEvent);
}
Thanks for posting this, it worked great for me. However (@Unity) It's really annoying that there's no way to accomplish this without replacing the StandaloneInput$$anonymous$$odule.
If any of you are lucky enough to be using Rewired, and you want to disable mouse clicks completely, you can use the RewiredStandaloneInput$$anonymous$$odule. It has a "Allow $$anonymous$$ouse Input" checkbox that can be turned off. Just make sure that if you use this, you need to remove/disable any regular StandaloneInput$$anonymous$$odule components that happen to be in the scene.
It's more so about just stopping the deselecting than allowing input. I can't believe we're all the way over on 2018.6 and there's still no way to do it.
The link to the Unity UI source code is no longer available, and the .zip download doesn't work. If anyone has the code, please tell me.
EDIT: I think I found it https://pastebin.com/$$anonymous$$LEHvTVN ANOTHER EDIT: This is just supported with the new input system now. Scroll down to see more details in my answer.
Answer by Rugbug_Redfern · Sep 18, 2020 at 01:05 AM
With the new Input System, you can just uncheck this box:
Perfect solution. For those who have the same problem and needs to fix it and use old EventSystems, there is an article which describes how to configure project: https://gamedevbeginner.com/input-in-unity-made-easy-complete-guide-to-the-new-system/
Thank you so much. This is exactly what im looking for
Answer by cjdev · Aug 23, 2015 at 07:24 PM
You could try using SetSelectedGameObject in the EventSystem to manually set the button as selected when the mouse is clicked like this:
using UnityEngine.EventSystems;
GameObject currentButton;
EventSystem eventSystem;
void Start ()
{
eventSystem = GameObject.Find("EventSystem").GetComponent<EventSystem>();
GameObject buttonObj = GameObject.Find("Button");
buttonObj.GetComponent<Button>().onClick.AddListener(() => { currentButton = buttonObj; });
}
void Update()
{
if (Input.GetMouseButtonDown(0))
eventSystem.SetSelectedGameObject(currentButton);
}
Hi, I have tried out the script and I am getting this error. http://prntscr.com/8820ep
Sorry the using UnityEngine.EventSystems;
goes above the class name, I just didn't want to include the whole class to make the answer shorter.
I have added the class name however, now a new error poped up. http://prntscr.com/882vi5
Sorry, I am not very good with program$$anonymous$$g and big thanks for helping out.
Oops, you'll also need using UnityEngine.UI;
If you like the interface I'd recommend using Visual Studio, it has a feature where you can right click and resolve to automatically put the using statement up top. I sometimes take that for granted.
For some reason the button still becomes unhighlighted when i left click. Is there a way to completely remove mouse functionality from the game and block any mouse related input?
I think first selected is only relevant when the scene is loaded and after that it doesn't matter what happens with it it will not re highlight that button or effect the scene in any way.
Answer by astracat111 · Feb 21, 2019 at 06:59 PM
You can use a low level mouse hook like so. This is not global (do NOT use a global hook for a video game). This is only if you're completely and utterly not going to use the mouse or touch screen in your entire game. Just create an instace of this object and do myMouse.EnableClicks() or myMouse.DisableClicks().
public class Mouse
{
#if UNITY_STANDALONE_WIN
public WindowsLowLevelHook windowsLowLevelHook = new WindowsLowLevelHook();
public void DisableClicks()
{
windowsLowLevelHook.Enable();
}
public void EnableClicks()
{
windowsLowLevelHook.Disable();
}
public class WindowsLowLevelHook
{
public bool enabled = false;
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
public HookProc hookProc;
public delegate void MouseHookCallback(MOUSEHOOKSTRUCT mouseHookStruct);
#region Events
public event MouseHookCallback LeftButtonDown;
public event MouseHookCallback LeftButtonUp;
public event MouseHookCallback RightButtonDown;
public event MouseHookCallback RightButtonUp;
public event MouseHookCallback MouseMove;
public event MouseHookCallback MouseWheel;
public event MouseHookCallback DoubleClick;
public event MouseHookCallback MiddleButtonDown;
public event MouseHookCallback MiddleButtonUp;
#endregion
public IntPtr hookID = IntPtr.Zero;
public void Enable()
{
hookProc = MouseProc;
hookID = SetHook(hookProc);
enabled = true;
}
public void Disable()
{
if (hookID == IntPtr.Zero)
return;
UnhookWindowsHookEx(hookID);
hookID = IntPtr.Zero;
enabled = false;
}
~WindowsLowLevelHook()
{
Enable();
}
private IntPtr SetHook(HookProc hookProc)
{
using (ProcessModule module = Process.GetCurrentProcess().MainModule)
return SetWindowsHookEx(WH_MOUSE, hookProc, GetModuleHandle(module.ModuleName), GetCurrentThreadId());
}
private IntPtr MouseProc(int nCode, IntPtr wParam, IntPtr lParam)
{
MOUSEHOOKSTRUCT lParamStruct = (MOUSEHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MOUSEHOOKSTRUCT));
if (nCode >= 0)
{
if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
{
return (IntPtr)1;
}
}
return CallNextHookEx(hookID, nCode, wParam, lParam);
}
#region WinAPI
private const int WH_MOUSE = 7;
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_LBUTTONDBLCLK = 0x0203,
WM_MBUTTONDOWN = 0x0207,
WM_MBUTTONUP = 0x0208
}
private Int32 GetWindowThreadProcessID(IntPtr hwnd)
{
Int32 pid = 1;
GetWindowThreadProcessId(hwnd, out pid);
return pid;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEHOOKSTRUCT
{
public POINT pt;
public IntPtr hwnd;
public uint wHitTestCode;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, Int32 dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll")]
private static extern Int32 GetCurrentThreadId();
#endregion
}
#endif
}
Your answer
Follow this Question
Related Questions
Click Goes Everywhere 0 Answers
Native resolution fullscreen breaks UI clicks 0 Answers
How do i disable my buttons while dragging ScrollRect? 0 Answers
How do you check if the object that you want to destroy with a click is the right object? 1 Answer
My inventory opens and closes on left mouse click when i don't want it to. 1 Answer