ISSUE-008
Unity默认键位卡手问题
常见表现
游戏自带键位支持但存在一些问题,例如:WASD走不动路、按键无法长按、按键无法连点。
相关源码
Unity引擎 UnityView+Keyboard.mm
static const double kKeyTimeoutInSeconds = 0.5;
- (void)processKeyboard
{
KeyMap& map = GetKeyMap();
if (map.size() == 0)
return;
std::vector<int> keysToUnpress;
double nowTime = GetTimeInSeconds();
for (KeyMap::iterator item = map.begin();
item != map.end();
item++)
{
// Key has expired, register it for key up event
if (nowTime - item->second > kKeyTimeoutInSeconds)
keysToUnpress.push_back(item->first);
}
for (std::vector<int>::iterator item = keysToUnpress.begin();
item != keysToUnpress.end();
item++)
{
map.erase(*item);
UnitySetKeyboardKeyState(*item, false);
}
}
原因分析
早期的iOS系统并没有提供键盘输入的API,所以Unity尝试通过UIKeyCommand这种取巧的方式来实现。但UIKeyCommand只支持按键按下事件,并没有提供按键抬起事件。所以Unity又尝试通过“0.5秒后自动松开”来模拟按键抬起,也就造成了游戏过程中按键卡手的情况。
自iOS 14.0起已经新增了GCKeyboard这样的键盘输入API,但Unity引擎并没有随之更新它的代码。
解决方法
玩家方面:通过PlayCover的按键映射去覆盖默认键位。
开发者方面:使用GCKeyboard API重写UnityView+Keyboard.mm。
有一份现成的版本:gist,但这个版本不支持设备断开重连,通过GCKeyboardDidConnectNotification和GCKeyboardDidDisconnectNotification可以监听到设备断开重连。