Hello,
is there a way in the editor to access clicks on the 4th and 5th mouse button?
Event.current.button does not seem to be anything but 0, 1 or 2 (as stated in the docs).
Ciao, Imi.
PS: I am not talking about the runtime player nor about the upcoming Unity UI from 4.6. I like to access the button in editor scripts to use for my custom EditorWindow. 
Iām hitting the same issue. For some reason, Unity believe a mouse only has 3 buttons.
Very late to the party, but I made a script for this, you can assign any commands to the mouse buttons:
// MouseButtonShortcuts in Assets/Editor
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
[FilePath("UserSettings/MouseButtonShortcuts.asset", FilePathAttribute.Location.PreferencesFolder)]
public class MouseButtonShortcuts : ScriptableSingleton<MouseButtonShortcuts>
{
// Middle button
[SerializeField] private string m_Button3 = "";
// Back button
[SerializeField] private string m_Button4 = "";
// Forward button
[SerializeField] private string m_Button5 = "";
#if UNITY_EDITOR_WIN
// Windows P/Invoke
[DllImport("user32.dll")]
private static extern short GetAsyncKeyState(int vKey);
#elif UNITY_EDITOR_OSX
// macOS NSEvent method signatures
[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")]
private static extern IntPtr objc_getClass(string className);
[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")]
private static extern IntPtr class_getClassMethod(IntPtr cls, IntPtr selector);
[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")]
private static extern IntPtr sel_registerName(string name);
[DllImport("/System/Library/Frameworks/AppKit.framework/AppKit")]
private static extern uint objc_msgSend_uint(IntPtr receiver, IntPtr selector);
#endif
// Start as true to avoid triggering on initial state
private static bool s_Button3Pressed = true;
private static bool s_Button4Pressed = true;
private static bool s_Button5Pressed = true;
[InitializeOnLoadMethod]
private static void Initialize()
{
EditorApplication.update += PollMouseButtons;
}
private static void PollMouseButtons()
{
bool button3State = false;
bool button4State = false;
bool button5State = false;
try
{
#if UNITY_EDITOR_WIN
// Windows: Use GetAsyncKeyState
button3State = (GetAsyncKeyState(0x04) & 0x8000) != 0; // Button 3
button4State = (GetAsyncKeyState(0x05) & 0x8000) != 0; // Button 4
button5State = (GetAsyncKeyState(0x06) & 0x8000) != 0; // Button 5
#elif UNITY_EDITOR_OSX
// macOS: Use NSEvent pressedMouseButtons
IntPtr nsEventClass = objc_getClass("NSEvent");
IntPtr selector = sel_registerName("pressedMouseButtons");
uint pressedButtons = objc_msgSend_uint(nsEventClass, selector);
button3State = (pressedButtons & (1u << 2)) != 0; // Button 3 (middle)
button4State = (pressedButtons & (1u << 3)) != 0; // Button 4
button5State = (pressedButtons & (1u << 4)) != 0; // Button 5
#endif
}
catch
{
// Fallback: macOS event polling failed
}
if (instance && button3State && !s_Button3Pressed)
{
HandleMouseButtonEvent(instance.m_Button3);
}
if (instance && button4State && !s_Button4Pressed)
{
HandleMouseButtonEvent(instance.m_Button4);
}
if (instance && button5State && !s_Button5Pressed)
{
HandleMouseButtonEvent(instance.m_Button5);
}
s_Button3Pressed = button3State;
s_Button4Pressed = button4State;
s_Button5Pressed = button5State;
}
public void SaveShortcuts()
{
name = "MouseButtonShortcuts";
Save(true);
}
private static void HandleMouseButtonEvent(string menuItemPath)
{
if (string.IsNullOrEmpty(menuItemPath))
{
return;
}
EditorApplication.delayCall += () =>
{
try
{
EditorApplication.ExecuteMenuItem(menuItemPath);
}
catch (Exception ex)
{
Debug.LogError($"Failed to execute menu item '{menuItemPath}': {ex.Message}");
}
};
}
private static List<string> GetAllMenuItems()
{
List<string> menuItems = new();
// Get all methods with MenuItem attribute using TypeCache
foreach (MethodInfo method in TypeCache.GetMethodsWithAttribute<MenuItem>())
{
foreach (MenuItem attribute in method.GetCustomAttributes<MenuItem>())
{
string menuItem = attribute.menuItem;
if (string.IsNullOrEmpty(menuItem))
{
continue;
}
// Filter out unwanted prefixes
if (menuItem.StartsWith("Assets/", StringComparison.Ordinal)
|| menuItem.StartsWith("CONTEXT/", StringComparison.Ordinal)
|| menuItem.StartsWith("internal:", StringComparison.Ordinal)
|| menuItem.StartsWith("GameObject/", StringComparison.Ordinal))
{
continue;
}
// Remove shortcut characters according to Unity's MenuItem rules
// Shortcuts come after a space character and use special modifiers:
// % (Ctrl/Cmd), ^ (Ctrl), # (Shift), & (Alt), _ (no modifier)
// Examples: "Menu/Item #&g", "Menu/Item _F1", "Menu/Item %#LEFT"
int lastSpaceIndex = menuItem.LastIndexOf(' ');
if (lastSpaceIndex >= 0)
{
// Check if what comes after the space looks like a shortcut
string afterSpace = menuItem.Substring(lastSpaceIndex + 1);
if (afterSpace.Length > 0)
{
char firstChar = afterSpace[0];
// If it starts with a modifier (%, ^, #, &, _) it's a shortcut
if (firstChar is '%' or '^' or '#' or '&' or '_')
{
menuItem = menuItem.Substring(0, lastSpaceIndex);
}
}
}
menuItems.Add(menuItem);
}
}
menuItems.Sort();
return menuItems;
}
[SettingsProvider]
public static SettingsProvider CreateProvider()
{
SettingsProvider provider = new("Preferences/Mouse Button Shortcuts", SettingsScope.User)
{
label = "Mouse Button Shortcuts",
activateHandler = (_, rootElement) =>
{
MouseButtonShortcuts settings = instance;
SerializedObject so = new(settings);
// title
Label title = new("Mouse Button Shortcuts");
title.style.unityFontStyleAndWeight = FontStyle.Bold;
title.style.fontSize = 14;
rootElement.Add(title);
HelpBox helpBox = new(
"Assign MenuItem paths to mouse buttons 3, 4, and 5. "
+ "These shortcuts will be triggered anywhere in the Unity Editor.",
HelpBoxMessageType.Info);
rootElement.Add(helpBox);
rootElement.Add(
CreateShortcutField("Mouse Button 3 (Middle)", so.FindProperty(nameof(m_Button3))));
rootElement.Add(
CreateShortcutField("Mouse Button 4 (Back)", so.FindProperty(nameof(m_Button4))));
rootElement.Add(
CreateShortcutField("Mouse Button 5 (Forward)", so.FindProperty(nameof(m_Button5))));
},
};
return provider;
}
private static VisualElement CreateShortcutField(string label, SerializedProperty prop)
{
VisualElement container = new();
List<string> allMenuItems = GetAllMenuItems();
List<string> choices = new() { "(None)" };
choices.AddRange(allMenuItems);
Label fieldLabel = new(label);
fieldLabel.style.marginTop = 4;
container.Add(fieldLabel);
DropdownField dropdown = new();
dropdown.choices = choices;
string currentValue = prop.stringValue;
dropdown.value = string.IsNullOrEmpty(currentValue) ? "(None)" : currentValue;
dropdown.RegisterValueChangedCallback(evt =>
{
string newValue = evt.newValue == "(None)" ? "" : evt.newValue;
prop.stringValue = newValue;
prop.serializedObject.ApplyModifiedProperties();
instance.SaveShortcuts();
});
container.Add(dropdown);
return container;
}
}