“[GCController 控制器]”不包含在应用程序启动之前连接的任何控制器

"[GCController controllers]" does not contain any controllers that were connected prior to application launch

"[GCController controllers]" does not contain any controllers that were connected prior to application launch

TLDR;

我正在尝试使用游戏控制器框架在 macOS 上实现游戏手柄输入。在我的代码中调用时,[GameController controllers] 总是 returns 一个空列表,直到连接了新的控制器。它从不反映在应用程序启动之前连接到 macOS 的游戏手柄,除非您在应用程序 运行 时断开它们并重新连接它们。有谁知道我需要做什么才能使 controllers 填充预启动连接?


完整问题

现在 Apple 已将对 Xbox 和 Playstation 控制器的支持添加到 GameController 框架中,我正在尝试将其用于我正在开发的 C++ 游戏引擎上的游戏手柄输入。我使用该框架而不是 IOKit 是为了“面向未来”我的游戏以支持将来的其他控制器类型,以及简化我自己的输入处理代码。

与许多其他游戏引擎一样,我放弃使用 NSApplicationMain() 和 nib 文件,转而实现我自己的事件循环并以编程方式设置我的游戏 window。虽然我的“Windows 风格”事件循环似乎工作正常,但我发现 [GCController controllers] 没有。数组 it returns 在启动时始终为空,并且只会反映在游戏 运行 时连接的控制器。断开预连接控制器不会触发我的 GCControllerDidDisconnectNotification 回调。

这是我的事件循环的简化版本:

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        // Create application
        [NSApplication sharedApplication];

        // Set up custom app delegate
        CustomAppDelegate * delegate = [[CustomAppDelegate alloc] init];
        [NSApp setDelegate:delegate];

        // Activate and launch app
        [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
        [NSApp setPresentationOptions:NSApplicationPresentationDefault];
        [NSApp activateIgnoringOtherApps:YES]; // Strictly speaking, not necessary
        [NSApp finishLaunching]; // NSMenu is set up at this point in applicationWillFinishLaunching:.

        // Initialize game engine (window is created here)
        GenericEngineCode_Init(); // <-- Where I want to call [GCController controllers]

        NSEvent *e;
        do
        {
            do
            {
                // Pump messages
                e = [NSApp nextEventMatchingMask: NSEventMaskAny
                                       untilDate: nil
                                          inMode: NSDefaultRunLoopMode
                                         dequeue: YES];
                if (e)
                {
                    [NSApp sendEvent: e];
                    [NSApp updateWindows];
                }
            } while (e);
        } while (GenericEngineCode_Run()); // Steps the engine, returns false when quitting.

        GenericEngineCode_Cleanup();
    }
    return 0;
}

我已经确认,即使使用 [NSApp run] 而不是 [NSApp finishLaunching],行为也是一样的。据我所知,问题是有些事情 NSApplicationMain() 我没有做,但那个功能是一个黑盒子——我无法确定我需要做什么才能得到 controllers 以正确填充。有谁知道我错过了什么?

我能找到的最接近这个问题的解释是 this answer,这表明我的应用没有收到 didBecomeActive 通知,或者至少,私有 _GCControllerManager 没有收到 CBApplicationDidBecomeActive 消息。不过,我不是专业的 macOS 开发人员:我不知道这是否真的适用于我的情况,或者如果适用,我将如何解决问题。

经过大量时间的搜索,我自己找到了答案。事实证明我的代码不是问题所在——问题是我的 Info.plist 文件由于我的构建系统出现问题而被删除了 CFBundleIdentifier 值。游戏控制器框架似乎需要包标识符才能在启动时正确填充 [GCController controllers]。虽然缺少 CFBundleIdentifier 无论如何都会是个问题,但作为一个 Windows 人,我并没有想到标识符可能用于 App Store 之外的其他东西,所以我让它滑到现在.

如果其他人遇到此问题,请确保您组装的应用程序包中 Info.plist 中的 CFBundleIdentifier 没有丢失或为空。在我使用 Premake 的情况下,我必须手动将 PRODUCT_BUNDLE_IDENTIFIER 设置为 xcodebuildsettings,以便 $(PRODUCT_BUNDLE_IDENTIFIER) 可以在 Info.plist.

中正确替换