Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Unwanted editor hotkeys in game mode

Discussion in 'Editor & General Support' started by guycalledfrank, May 13, 2013.

  1. Tonio1308

    Tonio1308

    Joined:
    Sep 22, 2013
    Posts:
    6
    This worked for me perfectly ! Thank you.
     
  2. ratking

    ratking

    Joined:
    Feb 24, 2010
    Posts:
    348
    Was annoyed by this too recently, so I took @Darkenstein's version and extended it so it only disables the shortcuts (and the toolbar) when the Game window is focused. The two #defines at the top should be self-explanatory, and can be commented out if wanted.

    Code (CSharp):
    1.  
    2. #define ACTIVATE_ONLY_WHEN_GAME_WINDOW_FOCUSED
    3. #define REMOVE_TOOLBAR_DURING_PLAY
    4.  
    5. // original: https://forum.unity.com/threads/unwanted-editor-hotkeys-in-game-mode.182073/#post-6964244
    6.  
    7. #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN
    8. using System;
    9. using System.Runtime.InteropServices;
    10. using System.Text;
    11. #endif
    12. using System.Linq;
    13. using UnityEditor;
    14. using UnityEditor.ShortcutManagement;
    15. using UnityEngine;
    16.  
    17. namespace EditorHelpers {
    18.  
    19.     [InitializeOnLoad]
    20.     public static class DisableShortcutsDuringPlay {
    21.         static bool activated = false;
    22.  
    23.         static DisableShortcutsDuringPlay() {
    24.             EditorApplication.playModeStateChanged += PlayModeStateChanged;
    25.             EditorApplication.quitting += Quitting;
    26.         }
    27.  
    28.         private static void PlayModeStateChanged(PlayModeStateChange playModeStateChange) {
    29.             switch (playModeStateChange) {
    30.                 case PlayModeStateChange.EnteredPlayMode:
    31. #if !ACTIVATE_ONLY_WHEN_GAME_WINDOW_FOCUSED
    32.                     Activate();
    33. #endif
    34.  
    35.                     new GameObject("DisableShortcutsDuringPlay", typeof(DisableShortcutsDuringPlayBehaviour));
    36.                     break;
    37.  
    38.                 case PlayModeStateChange.ExitingPlayMode:
    39.                     ShortcutManager.instance.activeProfileId = "Default";
    40.                     break;
    41.             }
    42.         }
    43.  
    44.         public static void Activate() {
    45.             if (activated) { return; }
    46.  
    47.             if (ShortcutManager.instance.GetAvailableProfileIds().Contains("Play")) {
    48.                 ShortcutManager.instance.activeProfileId = "Play";
    49.             }
    50.             else {
    51.                 ShortcutManager.instance.CreateProfile("Play");
    52.                 ShortcutManager.instance.activeProfileId = "Play";
    53.  
    54.                 foreach (string shortcutId in ShortcutManager.instance.GetAvailableShortcutIds()) {
    55.                     if (shortcutId != "Main Menu/Edit/Play") {
    56.                         ShortcutManager.instance.RebindShortcut(shortcutId, ShortcutBinding.empty);
    57.                     }
    58.                 }
    59.             }
    60.  
    61.             activated = true;
    62.        }
    63.         public static void Deactivate() {
    64.             if (!activated) { return; }
    65.             ShortcutManager.instance.activeProfileId = "Default";
    66.             activated = false;
    67.         }
    68.  
    69.         private static void Quitting() {
    70.             Deactivate();
    71.         }
    72.             }
    73.  
    74.     public class DisableShortcutsDuringPlayBehaviour : MonoBehaviour {
    75.  
    76. #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN
    77.         private delegate int EnumThreadWndProc(IntPtr hWnd, IntPtr lParam);
    78.      
    79.         [DllImport("user32.dll")] static extern int EnumThreadWindows(uint dwThreadId, EnumThreadWndProc lpfn, IntPtr lParam);
    80.         [DllImport("kernel32.dll")] static extern uint GetCurrentThreadId();
    81.         [DllImport("user32.dll")] static extern int GetClassNameA(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    82.      
    83.         [DllImport("user32.dll")] private static extern IntPtr GetMenu(IntPtr hWnd);
    84.         [DllImport("user32.dll")] private static extern int SetMenu(IntPtr hWnd, IntPtr hMenu);
    85.         [DllImport("user32.dll")] private static extern int DrawMenuBar(IntPtr hWnd);
    86.      
    87.         [DllImport("user32.dll")] private static extern int GetWindowLongA(IntPtr hWnd, int nIndex);
    88.         [DllImport("user32.dll")] private static extern int SetWindowLongA(IntPtr hWnd, int nIndex, int dwNewLong);
    89.      
    90.         private const int GWL_STYLE = -16;
    91.      
    92.         private const int WS_CAPTION = 0x00C00000;
    93.         private const int WS_SYSMENU = 0x00080000;
    94.      
    95.         private IntPtr hFrameWnd;
    96.         private IntPtr hFrameMenu;
    97.  
    98.         bool inactiveToolbar;
    99. #endif
    100.  
    101.         private void Awake() {
    102. #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN
    103.             int EnumThreadWndProc(IntPtr hWnd, IntPtr lParam) {
    104.                 StringBuilder className = new StringBuilder(64);
    105.                 GetClassNameA(hWnd, className, 64);
    106.                 if (className.ToString() == "UnityContainerWndClass") {
    107.                     hFrameWnd = hWnd;
    108.                     hFrameMenu = GetMenu(hWnd);
    109.                     return 0;
    110.                 }
    111.                 return 1;
    112.             }
    113.             EnumThreadWindows(GetCurrentThreadId(), EnumThreadWndProc, IntPtr.Zero);
    114. #endif
    115.             gameObject.hideFlags = HideFlags.HideInHierarchy;
    116.  
    117.             GameObject.DontDestroyOnLoad(gameObject);
    118.         }
    119.  
    120. #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN
    121.         void ActivateToolbar() {
    122.             if (!inactiveToolbar) { return; }
    123.             SetWindowLongA(hFrameWnd, GWL_STYLE, GetWindowLongA(hFrameWnd, GWL_STYLE) | (WS_CAPTION | WS_SYSMENU));
    124.             SetMenu(hFrameWnd, hFrameMenu);
    125.             DrawMenuBar(hFrameWnd);
    126.             inactiveToolbar = false;
    127.         }
    128.  
    129.         void DeactivateToolbar() {
    130.             if (inactiveToolbar) { return; }
    131.             SetWindowLongA(hFrameWnd, GWL_STYLE, GetWindowLongA(hFrameWnd, GWL_STYLE) & ~(WS_CAPTION | WS_SYSMENU));
    132.             SetMenu(hFrameWnd, IntPtr.Zero);
    133.             DrawMenuBar(hFrameWnd);
    134.             inactiveToolbar = true;
    135.         }
    136. #endif
    137.  
    138.         private void Update() {
    139. #if ACTIVATE_ONLY_WHEN_GAME_WINDOW_FOCUSED
    140.             if (EditorWindow.focusedWindow != null && EditorWindow.focusedWindow.titleContent.text == "Game") {
    141.                 DisableShortcutsDuringPlay.Activate();
    142. #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN
    143.                  DeactivateToolbar();
    144. #endif
    145.            }
    146.             else {
    147.                 DisableShortcutsDuringPlay.Deactivate();
    148. #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN
    149.                  ActivateToolbar();
    150. #endif
    151.            }
    152. #else
    153.  
    154. #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN
    155.             if (Time.frameCount == 3) {
    156.                 DeactivateToolbar();
    157.             }
    158. #endif
    159.  
    160. #endif
    161.         }
    162.  
    163.         private void OnDestroy() {
    164. #if REMOVE_TOOLBAR_DURING_PLAY && UNITY_EDITOR_WIN
    165.             ActivateToolbar();
    166. #endif
    167.             DisableShortcutsDuringPlay.Deactivate();
    168.         }
    169.     }
    170.  
    171. }
    172.  
     
    Last edited: Dec 7, 2021
    Marc-Saubion likes this.
  3. Yiming075

    Yiming075

    Joined:
    Mar 24, 2017
    Posts:
    29
    We need a fix
     
  4. DinkleDorph

    DinkleDorph

    Joined:
    Mar 25, 2022
    Posts:
    1
    Reviving again, this is still an issue O_O
     
    alexniver, visca_c and Marc-Saubion like this.
  5. DerDicke

    DerDicke

    Joined:
    Jun 30, 2015
    Posts:
    291
    Man... Ran into it. Couldn't believe that Input goes to Editor when Game Window is active. Who does this?
     
  6. joshmccready

    joshmccready

    Joined:
    Oct 12, 2013
    Posts:
    2
    Somewhat less complicated version of the evolving solution posted before but which avoids the whole windows api stuff and just simply disables any or all unwanted hotkeys when in play mode:
    Code (CSharp):
    1. using System.Linq;
    2. using UnityEditor;
    3. using UnityEditor.ShortcutManagement;
    4.  
    5. [InitializeOnLoad]
    6. public static class EnterPlayModeBindings
    7. {
    8.     static EnterPlayModeBindings()
    9.     {
    10.         EditorApplication.playModeStateChanged += ModeChanged;
    11.         EditorApplication.quitting += Quitting;
    12.     }
    13.     static void ModeChanged(PlayModeStateChange playModeState)
    14.     {
    15.         if (playModeState == PlayModeStateChange.EnteredPlayMode)
    16.         {
    17.             if (!ShortcutManager.instance.GetAvailableProfileIds().Contains("PlayGameDisableCommands"))
    18.             {
    19.                 UnityEngine.Debug.Log("Creating PlayGameDisableCommands Shortcut profile");
    20.                 ShortcutManager.instance.CreateProfile("PlayGameDisableCommands");
    21.                 ShortcutManager.instance.activeProfileId = "PlayGameDisableCommands";
    22.                
    23.                 // Disable all the shortcuts.
    24.                
    25.                 // var possibleShortcuts= ShortcutManager.instance.GetAvailableShortcutIds();
    26.                 // foreach (var shortcut in possibleShortcuts)
    27.                 // {
    28.                 //     ShortcutManager.instance.RebindShortcut(shortcut,ShortcutBinding.empty);
    29.                 //
    30.                 // }
    31.                
    32.                 // Or just pick some specific shortcuts to disable
    33.                
    34.                 ShortcutManager.instance.RebindShortcut("Main Menu/Edit/Copy",ShortcutBinding.empty);
    35.                 ShortcutManager.instance.RebindShortcut("Main Menu/Edit/Paste",ShortcutBinding.empty);
    36.                 ShortcutManager.instance.RebindShortcut("Main Menu/Edit/Undo",ShortcutBinding.empty);
    37.                 ShortcutManager.instance.RebindShortcut("Main Menu/Edit/Redo",ShortcutBinding.empty);
    38.                 ShortcutManager.instance.RebindShortcut("Main Menu/Edit/Select All",ShortcutBinding.empty);
    39.             }
    40.             ShortcutManager.instance.activeProfileId = "PlayGameDisableCommands";
    41.         }else if (playModeState == PlayModeStateChange.EnteredEditMode)
    42.         {
    43.             ShortcutManager.instance.activeProfileId = "Default";
    44.            
    45.             // optionally clean up after yourself
    46.             ShortcutManager.instance.DeleteProfile("PlayGameDisableCommands");
    47.         }
    48.            
    49.     }
    50.     static void Quitting()
    51.     {
    52.         ShortcutManager.instance.activeProfileId = "Default";
    53.        
    54.         // optionally clean up after yourself
    55.         ShortcutManager.instance.DeleteProfile("PlayGameDisableCommands");
    56.     }
    57. }
     
    Last edited: May 27, 2022
    fffMalzbier likes this.
  7. DerDicke

    DerDicke

    Joined:
    Jun 30, 2015
    Posts:
    291
    Much more elegant solution using OnApplicationFocus(). HotkeyProfile is set/reset on PlayMode Window get/loose focus. Tested.

    Code (CSharp):
    1. #if UNITY_EDITOR
    2. using System.Linq;
    3. using UnityEditor.ShortcutManagement;
    4. using UnityEngine;
    5.  
    6.  
    7. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    8. /*
    9.     DisableShortcutsOnPlay, creates a HotkeyProfile with everything disabled but EndPlayMode- Hotkey.
    10.     Sets it every time Play Mode window gets focus, resets it when focus goes away.
    11. */
    12. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    13. namespace SnapBuilder
    14. {
    15.  
    16.     public class DisableShortcutsOnPlay : MonoBehaviour
    17.     {
    18.         string oldProfile;
    19.         public string pmProfile= "SnapBuilder.PlayModeHotkeyProfile";
    20.  
    21.         void CreateProfile()
    22.         {
    23.             /*
    24.             // out comment in case of changes to profile
    25.             if (HasProfile())
    26.             {
    27.                 ShortcutManager.instance.DeleteProfile(pmProfile);
    28.             }
    29.             */
    30.  
    31.             if (!HasProfile())
    32.             {
    33.                 string curProfile = ShortcutManager.instance.activeProfileId; // save
    34.  
    35.                 ShortcutManager.instance.CreateProfile(pmProfile);
    36.                 ShortcutManager.instance.activeProfileId = pmProfile;
    37.  
    38.                 foreach (string shortcutId in ShortcutManager.instance.GetAvailableShortcutIds())
    39.                 {
    40.                     if (shortcutId != "Main Menu/Edit/Play") // leave shortcut to end PlayMode alone
    41.                     {
    42.                         ShortcutManager.instance.RebindShortcut(shortcutId, ShortcutBinding.empty);
    43.                     }
    44.                 }
    45.  
    46.                 ShortcutManager.instance.activeProfileId = curProfile;
    47.             }
    48.         }
    49.  
    50.  
    51.         bool HasProfile()
    52.         {
    53.             return ShortcutManager.instance.GetAvailableProfileIds().Contains(pmProfile);
    54.         }
    55.  
    56.  
    57.         void OnApplicationFocus(bool hasFocus)
    58.         {
    59.             //Debug.Log("Focus= "+hasFocus);
    60.             if (hasFocus)  ShortcutManager.instance.activeProfileId = pmProfile;
    61.             else ShortcutManager.instance.activeProfileId = oldProfile;
    62.         }
    63.  
    64.  
    65.         //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    66.         /*
    67.             Unity
    68.         */
    69.         //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    70.  
    71.         void Awake()
    72.         {
    73.             //Debug.Log("Awake");
    74.             oldProfile = ShortcutManager.instance.activeProfileId; // save
    75.             CreateProfile();
    76.         }
    77.  
    78.         void OnDestroy()
    79.         {
    80.             // safety net in case user removes or disables this script in Play Mode
    81.             ShortcutManager.instance.activeProfileId = oldProfile;
    82.         }
    83.  
    84.  
    85.  
    86.     }// class
    87. }
    88.  
    89. #endif
    90.  
     
  8. ribbanya

    ribbanya

    Joined:
    Feb 28, 2019
    Posts:
    9
    This has been fixed in 2020.3.37f1, 2021.3.7f1, and 2022.2.0a9.

    A toggle appears in the top right corner of the game view that disables shortcuts.

    upload_2022-7-28_8-24-27.png
     
  9. jlnorris

    jlnorris

    Joined:
    May 17, 2022
    Posts:
    6
    Thanks! I had this issue with ALT + SPACE (two separate commands but they could be pressed together) and your hack fixed it.

    The big problem in my case was that Unity stops tracking keys when play mode is paused.

    So e.g. if I have my "forward" button pressed when the game is paused because of this, Unity doesn't detect that I have released the forward key while the game is paused. Then when I unpause the game, it still thinks I've got the "forward" button pressed and I have to press and release it again for it to detect it being released. This is a nightmare when trying to test a game that is high-intensity and needs a fast precision response to the gameplay.