最新学习Unity的Animator,做了一个简单的控制人物待机、走跑和跳跃动作的study project。其中一个控制规则是按下W走,按下Shift+W跑,按着Shift+W的同时按空格键则播放跳的动作。
  走跑都很顺利,跳却一直跳不起来。一开始以为是状态机或代码问题,但是检查了一下,没有问题。如果动作、状态机和控制代码都没有问题,那就很可能是按下空格键的时候没有响应咯?
  OK,写测试代码:
 1 void Update()
 2 {
 3  if (Input.GetKeyDown(KeyCode.LeftShift))
 4         {
 5             Debug.Log("Shift key down");
 6         }
 7  if (Input.GetKeyDown(KeyCode.Space))
 8         {
 9             Debug.Log("Space key down");
10         }
11
12         if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.Space))//①
13         {
14             Debug.Log("LeftShift and Space key down");
15         }
16 }

  注意①使用Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.Space)而非Input.GetKeyDown(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.Space)的原因:Input.GetKeyDown只会在你按下键位的那一帧检测到并返回True,后面将返回False,直到你重新再按下该键。所以,如果你能保证可以在同一帧同时按下shift+space,那你也可以这么用...我试过了,概率很低很低==!
  来看看输出:
  按下左shift时:
  
  按下空格键时:
     
  同时按下shift和空格键时:
   
 
  空格键呢....
  OK,确认是键位没有正常响应了,shift正常,space正常,那到底是什么导致shift+space没有正常响应呢?
  最有可能的就是该组合键(热键)被其他程序占用了。那怎么知道shift+space是不是被占用了,被什么程序占用了呢?

  有兴趣和胆量的话可以试试 Windows Hotkey Explorer 这款热键冲突检测的软件

 Windows Hotkey Explorer 可以显示当前已被占用的快捷键,并定位到相关程序
 
  需要胆量是因为:
  
  结果我也中招了(Win 10)...所以慎用。但是好歹检测出来shift+space的确已经被注册占用了。一般这种情况下多看看桌面的右下角...找到了
  
  原来是输入法程序占用了Shift+Space
 
其实知道怎么注册热键的话也可以自己写一小段代码测试有没有被占用:
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Runtime.InteropServices;
 4
 5 namespace Neo
 6 {
 7     public class HotKeyRegisterCheck
 8     {
 9         [DllImport("user32.dll")]
10         public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint control, uint keycode);
11
12         [DllImport("user32.dll")]
13         public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
14
15         /// <summary>
16         /// 通过尝试注册热键来判断是否已被占用
17         /// </summary>
18         /// <param name="control">控制键,如ctrl,alt和shift等</param>
19         /// <param name="keyCode">和控制键组合的键值</param>
20         /// <returns>指定的组合键是否已经注册过</returns>
21         public static bool CheckHotKeyIsRegistered(uint control,uint keyCode)
22         {
23             bool registerResult = RegisterHotKey((IntPtr)null, 999, control, keyCode);//注册热键
24             if (registerResult) UnregisterHotKey((IntPtr)null, 999);//因为我们仅是检测,所以如果注册成功了还得取消注册
25
26             return !registerResult;
27         }
28     }
29 }

使用:
1 void Start()
2 {
3         bool result = HotKeyRegisterCheck.CheckHotKeyIsRegistered(0x0004, 0x20);//Shift+Space
4         Debug.Log("热键是否已被注册过:" + result);
5  }

看看结果:

  其实就是用win api尝试注册热键,如果能注册成功则说明还没有被占用,否则就是已被其他程序注册过了。关于要传入的组合键的值可以参考
  控制键https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms646309(v=vs.85).aspx
  其他键https://msdn.microsoft.com/zh-cn/library/windows/desktop/dd375731(v=vs.85).aspx
  控制键支持Ctrl、Alt、shift和Win
  既然可以动态检测组合键有没有被占用,那我们就有办法来规避这种情况。比如游戏内默认设定Shift+Space为跑跳的同时再设置几组组合键作为备用,通过上述检测方法一一验证,直到发现没有被占用的组合键。但是,这不仅增加了工作量,更为关键的是对组合键使用默认习惯的一种挑战,毕竟大家基本都习惯Shift跑Space跳Shift+Space跑跳。为了解决这个问题,我们可能就要舍弃Unity提供的Input类或者可以与其结合使用--自己实现键盘监控
先看代码(网上找的,略微做了些修改):
  1 using System;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4 using System.Runtime.InteropServices;
  5 using System.Windows.Forms;
  6
  7 namespace Neo
  8 {
  9     public class KeybordHook
 10     {
 11         public struct KeyMSG
 12         {
 13             public int vkCode;
 14             public int scanCode;
 15             public int flags;
 16             public int time;
 17             public int dwExtraInfo;
 18         }
 19
 20         #region 第一步:声明API函数
 21         //使用钩子,需要使用WindowsAPI函数,所以要先声明这些API函数。
 22
 23         // 安装钩子
 24         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
 25         public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
 26
 27         // 卸载钩子
 28         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
 29         public static extern bool UnhookWindowsHookEx(int idHook);
 30
 31         // 继续下一个钩子
 32         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
 33         public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
 34
 35         // 取得当前线程编号
 36         [DllImport("kernel32.dll")]
 37         static extern int GetCurrentThreadId();
 38
 39         #endregion
 40
 41         #region 第二步:声明,定义委托
 42         public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
 43
 44         static int hKeyboardHook = 0;//如果hKeyboardHook不为0则说明钩子安装成功
 45
 46         HookProc KeyboardHookProcedure;
 47         #endregion
 48
 49         #region 第三步:编写钩子子程
 50         //钩子子程就是钩子所要做的事情。
 51         private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr IParam)
 52         {
 53             if (nCode >= 0)
 54             {
 55                 int ret = 1;
 56                 //这一步是将IParam的信息提取到自定义的struct里面。注释掉是因为在我这里会导致unity莫名退出,很奇怪
 57                 //KeyMSG m = (KeyMSG)Marshal.PtrToStructure(IParam, typeof(KeyMSG));
 58                 if (IParam.ToInt32() > 0)
 59                 {
 60                     Debug.Log("键盘按下:" + wParam);
 61                 }
 62                 else if (IParam.ToInt32() < 0)
 63                 {
 64                     Debug.Log("键盘抬起:" + wParam);
 65                 }
 66
 67                 if (ret == 1) CallNextHookEx(hKeyboardHook, nCode, wParam, IParam);//出于礼貌,如果要丢弃按键消息,最好先让后续的钩子处理该消息
 68                 return ret;//0:按键消息将继续传递给windows消息处理函数  1:直接丢弃按键消息,不会传给windows消息处理函数
 69             }
 70             return CallNextHookEx(hKeyboardHook, nCode, wParam, IParam);
 71         }
 72         #endregion
 73
 74         #region 第四步:正式启用钩子
 75         //钩子安装
 76         public void HookStart()
 77         {
 78             if (hKeyboardHook == 0)
 79             {
 80                 //创建HookProc实例
 81                 KeyboardHookProcedure = new HookProc(KeyboardHookProc);
 82                 //设置钩子,第一个参数2表示此钩子为线程钩子
 83                 hKeyboardHook = SetWindowsHookEx(2, KeyboardHookProcedure, IntPtr.Zero, GetCurrentThreadId());
 84
 85                 if (hKeyboardHook == 0)
 86                 {
 87                     //终止钩子
 88                     throw new Exception("安装钩子失败");
 89                 }
 90                 else
 91                 {
 92                     Debug.Log("安装钩子成功");
 93                 }
 94             }
 95         }
 96
 97         //钩子卸载
 98         public void HookStop()
 99         {
100             bool retKeyboard = true;
101             if (hKeyboardHook != 0)
102             {
103                 retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
104                 hKeyboardHook = 0;
105             }
106             if (!retKeyboard)
107                 throw new Exception("钩子卸载失败");
108
109         }
110         #endregion
111     }
112 }

使用起来也很简单:
1 KeybordHook kh = new KeybordHook();
2 //开始键盘监控
3 kh.HookStart();

当要结束监控时:
1 kh.HookStop();

输出:
 在shift按下的时候成功的监听到了space按下的消息
  KeyboardHookProc函数获得了键盘的物理击键数据,然后就可以根据这些数据编写自己的Input类了,这里就不继续深入了。关于键盘监控,可以参考http://www.cnblogs.com/grenet/archive/2010/12/07/1898840.html
 
  目前来说,比较好的做法是,如果你的游戏需要使用组合键而你又担心会被占用时,可以通过实现自己的键盘监控来避免这种情况的发生。实际操作时,可以先通过上边提到的检测方法来确定游戏所使用的所有组合键有没有被占用,没有被占用就使用Unity提供的Input,否则使用自己的Input。当然,两者其实可以结合使用以达到减少自己实现Input的代码量和尽量使用原生Input类的目的

转载于:https://www.cnblogs.com/zion-world/p/5869462.html

游戏使用的组合键(热键)被占用的一种解决方案相关推荐

  1. Windows 常用组合键(热键)

    1.创建一个新的window桌面:windows + ctrl + D 2.虚拟桌面之间的切换:windows + ctrl + 左右箭头键 3.关闭虚拟桌面wndows + ctrl + F4关闭虚 ...

  2. 键盘组合键映射_如何在键盘上重新映射Office键

    键盘组合键映射 The Office Key is a new key that you'll find on Microsoft keyboards. It lets you quickly lau ...

  3. 嵌入式Linux驱动笔记(三十一)------SYSRQ组合键使用

    你好!这里是风筝的博客, 欢迎和我一起交流. ALT+SYSRQ组合键是Linux调试的一种手段,即使在系统死机.panic.卡住等情况,只要系统还能响应中断,那么SYSRQ就派上用场了(比如触发cr ...

  4. 嵌入式linux按键扫描,嵌入式Linux驱动笔记(三十一)------SYSRQ组合键使用

    你好!这里是风筝的博客, 欢迎和我一起交流. ALT+SYSRQ组合键是Linux调试的一种手段,即使在系统死机.panic.卡住等情况,只要系统还能响应中断,那么SYSRQ就派上用场了(比如触发cr ...

  5. 最好的电脑系统_热键被占用怎么办?电脑系统 程序 游戏热键被占用冲突如何解决?...

    最近有位朋友在使用电脑的时候,遇到了热键被占用的问题,不知道怎么去解决.其实,Windows系统程序 软件热键被占用的情况,通常是因为同一个热键,被不同的程序使用,无法兼容,产生冲突.下面就来看看电脑 ...

  6. Android TV热键(快捷键、组合键)实现

    TV上一些特殊的功能入口.串口打印开关.adb调试开关.部分菜单的显示隐藏等都可以通过热键来控制. 一般组合键选用某个功能键+一串数字即可,我们可以将其封装成工具类,这里快捷键,我使用F1和几个数字键 ...

  7. 制作菜单栏、选择题、搓组合键、小僵尸-unity3D游戏开发入门

    0.键盘事件 任务一:编写菜单栏 任务二:做一道单项选择题 任务三:写多项选择题(多选错选不得分,少选得一半分,80分以上赏朵小红花) 任务四:键盘键响应 通过敲ASDW方向键在屏幕上打出相应方向箭头 ...

  8. Alfred 功能组合键/快捷键

    文章目录 快捷键 如何设置呼出热键 参考文章 快捷键 快捷键 说明 Fn 在选中的文件或者目录上点击 Fn 键可以触发其额外的操作,可以在[Actions]里面进行配置 Command + Enter ...

  9. 这是高手最常用的第一快捷组合键 - imsoft.cnblogs

    1.锁定电脑 2.要找电脑上的文件时,一般人会先找到"我的电脑",然后点击打开,而高手总是很酷的,轻轻按下键盘上的Windows键不放然后再按E键,直接打开电脑的资源管理器,而一般 ...

最新文章

  1. 大白菜软件常用功能介绍
  2. 学习python装饰器_Python装饰器学习(九步入门)
  3. 【EventBus】事件通信框架 ( 订阅方法注册 | 检查订阅方法缓存 | 反射获取订阅类中的订阅方法 )
  4. Python 技术篇-用os库读取本地文件的字节数、文件大小
  5. R语言--查看数据类型+类型判断
  6. android之隐藏状态栏、图标、布局
  7. LeetCode 34 Search for a Range(搜索范围)
  8. WebService学习总结(6)——WebService常用接口
  9. 树莓派3安装系统linux,树莓派3 安装Fyde OS
  10. kali linux窗口变大,kali怎么把屏幕放大
  11. 树莓派基础实验12:PCF8591模数转换器实验
  12. 阅读小技能:读透一本书( 链接旧的概念和体验)
  13. 【FPGA】SPI协议
  14. Python--数字炸弹游戏
  15. 运用审查元素下载网页视频
  16. 产品运营数据分析—SPSS数据分组案例
  17. 简述如何编写java程序_1-4 简述 Eclipse 编写 Java 程序的流程。_学小易找答案
  18. 服务器电源输出电压不稳定,电源模块输出电压变低的原因和解决方法
  19. MongoDB的C#官方驱动InvalidOperationException异常的解决办法
  20. ubuntu i386在32位机器上安装

热门文章

  1. c# api返回后执行代码_API错误代码是历史记录-请尝试执行此操作
  2. 一本C语言的好书——《C语言的科学与艺术》
  3. playwright实战篇(tx、ali225)
  4. FPGA笔记 Cyclone IV 供电电源
  5. 前端的小玩意(9.2)——做一个仿360工具箱的web页面(全部工具里面的模板)
  6. 常见的爬虫类型有什么?
  7. 急,大数据实验室出了问题怎么解决
  8. mof定制材料|氨基功能化修饰PIM-1/MOF|乙二胺四乙酸(EDTA)修饰MOF(UiO-66)|Mn–MOF修饰为荧光Eu~(3+)@Mn–MOF
  9. Springboot+WebSocket 自动重连机制
  10. 使用HTML5监测网站性能