> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 用户与输入设备

> 用户与输入设备

游戏需要知道哪些输入设备与指定用户相关联。
这对于回答以下问题至关重要:

* 在游戏中是谁执行了某个操作?

* 谁获得了成就?

* 谁在进行购买?

本主题涵盖了一些关键概念,可帮助你处理这些关联并回答
这类问题。

## XBOX One ERA 与 Microsoft 游戏开发工具包(GDK)之间用户模型的差异

无论你是开发一款新的 Microsoft 游戏开发工具包(GDK)游戏,还是从 XBOX One ERA 移植旧游戏,如果你习惯了 XBOX One ERA 的用户模型,实现用户与输入设备管理时可能会有些困惑。

* 需要用户的游戏,例如需要游戏存档或成就的游戏,必须建立一个主要
  用户。这个主要用户是仅存在于游戏中的概念,不由系统提供。

* 游戏只知道通过调用 [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 添加的用户。游戏不会被
  告知系统为其未添加的用户所做的任何操作。

* 当之前与游戏用户关联的设备关联到游戏未知的用户时,
  游戏只会被通知一个没有新用户的设备关联事件。

* 如果一个未与游戏用户关联的设备关联到另一个也未通过
  [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 添加的用户,则游戏不会被通知该关联事件。

* 账户选择器(Account Picker)的行为会因其如何被调出而不同(系统指南 vs
  [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync))。

<Note>UserManagement 示例涵盖了各种游戏情境下的用户管理和输入设备配对
行为。它还处理与用户和输入设备相关的 XR 要求。有关示例的详细信息,请参见
[Microsoft 游戏开发工具包示例](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/development-downloads/gdk-samples-home)。</Note>

## 如何标识指定用户

游戏使用 *本地 ID* 来与输入设备交互。本地 ID 是一种
在游戏会话内伴随用户整个生命周期的标识符。本地 ID 可用于
游戏派生的任何进程之间,或者当游戏
调用 [XLaunchNewGame](/reference/system/xgame/functions/xlaunchnewgame) 时。不要使用本地 ID
跨游戏会话标识用户。

要获取用户的本地 ID,请使用 [XUserGetLocalId](/reference/system/xuser/functions/xusergetlocalid) 函数。

## 如何标识特定的输入设备

游戏设备,例如手柄、街机摇杆和方向盘,都有一个
唯一的 *设备 ID*,由 [APP\_LOCAL\_DEVICE\_ID](/reference/system/xuser/structs/app_local_device_id) 结构体表示。
此设备 ID 在游戏多次启动或
系统重启之间保持一致。同一系统上运行的两款不同游戏之间的设备 ID
不同。

如果你在主机上使用 `XInput`,可以通过
[XInputGetDeviceId](/reference/input/xinputongameinput/functions/xinputgetdeviceid) 获取设备 ID。

如果你使用 [GameInput](/build/core-features/common/input/overviews/input-overview),你可以从调用 [IGameInputDevice::GetDeviceInfo](/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_getdeviceinfo) 返回的
[GameInputDeviceInfo](/reference/input/gameinput/structs/gameinputdeviceinfo) 对象的 `deviceId` 成员中获取设备 ID。

## 用户模型

当游戏需要有用户时,例如需要游戏存档或成就时,游戏
完全负责建立主要用户。即使允许多个用户登录,也必须维护此主要用户。游戏还必须允许根据需要更改主要
用户。一种方法是提供 *切换用户* 提示,通过 [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 调出账户选择器。

账户选择器列出所有之前登录过主机的用户,
带有用于登录新账户的 **添加新账户** 按钮,并允许登录临时
访客用户。可以选择这些用户账户中的任何一个,与用户的真实
身份无关。系统支持以这种方式选择扮演其他人的
用户。

Microsoft 游戏开发工具包(GDK)游戏并不完全知晓系统上的用户。相反,用户只能通过对 [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 的调用添加到游戏中。以这种方式添加的用户是
游戏可与之交互的唯一用户。系统不会通知游戏关于
游戏未添加用户所做操作的信息。因此,游戏应维护其自身的用户列表。

账户选择器可以通过两种不同的方式被调出:从系统指南以及通过
[XUserAddAsync](/reference/system/xuser/functions/xuseraddasync)。在这两种情况下,此选择器的行为不同:

| 情况           | [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 账户选择器 | 指南账户选择器                     |
| ------------ | ---------------------------------------------------------------------- | --------------------------- |
| 选择尚未登录到游戏的用户 | 该用户同时登录到系统和游戏中。                                                        | 该用户仅登录到系统。游戏不会收到该登录的通知。     |
| 选择已登录到游戏的用户  | 该用户已登录到游戏,因此不会发生进一步的用户状态变化。                                            | 该用户已登录到游戏,因此不会发生进一步的用户状态变化。 |

<Note>登录到游戏的用户集合始终是登录到系统的用户
集合的子集。游戏不能拥有系统未登录的用户。
但是,系统可以拥有游戏不知道的用户。</Note>

用户事件可以通过使用 [XUserRegisterForChangeEvent](/reference/system/xuser/functions/xuserregisterforchangeevent) 注册的
[XUserChangeEventCallback](/reference/system/xuser/functions/xuserchangeeventcallback) 处理。事件只会为使用 [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 登录的用户触发。
当用户从系统注销时,游戏必须做出相应的反应,或者从游戏中移除用户,或者允许玩家
尝试再次登录该用户。

## 输入设备关联

Microsoft 游戏开发工具包(GDK)允许用户关联任意数量的输入设备。在移植可能假设用户与设备为 1:1 映射的旧游戏时,这可能会带来
挑战。

设备关联通常通过账户选择器建立。从 UI 中选择用户的输入设备
会与该用户关联。关联也可能因其他情况发生变化,例如当
用户注销时,或者当使用 [AddDefaultUserSilently](/reference/system/xuser/enums/xuseraddoptions) 和 [AddDefaultUserAllowingUI](/reference/system/xuser/enums/xuseraddoptions) 选项无 UI 地调用 [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 时。

账户选择器在关联方面也会根据其被调出方式而有不同的行为:

| 情况           | [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 账户选择器 | 指南账户选择器                                                 |
| ------------ | ---------------------------------------------------------------------- | ------------------------------------------------------- |
| 选择尚未登录到游戏的用户 | 用户登录到游戏后,完成提示的设备会与该用户关联。                                               | 该用户登录到系统(如果尚未登录),完成提示的设备关联到该用户。由于游戏不知道该用户,游戏会被告知该设备未关联。 |
| 选择已登录到游戏的用户  | 完成提示的设备与系统和游戏用户相关联。                                                    | 完成提示的设备与系统和游戏用户相关联。                                     |

如果通过使用
[AddDefaultUserSilently](/reference/system/xuser/enums/xuseraddoptions) 或 [AddDefaultUserAllowingUI](/reference/system/xuser/enums/xuseraddoptions) 选项之一调用 [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 在没有账户选择器的情况下自动将用户登录到游戏,则系统已有的输入设备配对
会传达给游戏。

要收到用户设备关联变化的通知,你可以使用
[XUserRegisterForDeviceAssociationChanged](/reference/system/xuser/functions/xuserregisterfordeviceassociationchanged) 方法注册
[XUserDeviceAssociationChangedCallback](/reference/system/xuser/functions/xuserdeviceassociationchangedcallback) 回调。你也可以调用 [XUserFindForDevice](/reference/system/xuser/functions/xuserfindfordevice) 查询特定设备的关联。

<Note>由于游戏只能知道通过
[XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 添加的用户,用户设备关联回调和方法只能返回游戏
之前添加过的用户。</Note>

## 将用户匹配到默认音频端点

耳机或麦克风常常与游戏一起提供。以下是一些重要的
需要询问的问题。

* 用户是否有耳机?如果有,他们可能使用的是哪个耳机?
  默认的通信渲染音频端点是什么?

* 用户是否有与之关联的麦克风?
  默认的通信捕获端点是什么?

要为特定用户回答这些问题,游戏可以调用
[XUserGetDefaultAudioEndpointUtf16](/reference/system/xuser/functions/xusergetdefaultaudioendpointutf16)。就像用户到设备的
关联可以变化一样,与特定用户关联的默认音频端点
也可以变化。要检测这些关联变化,游戏
应调用 [XUserRegisterForDefaultAudioEndpointUtf16Changed](/reference/system/xuser/functions/xuserregisterfordefaultaudioendpointutf16changed) 并留意生成的回调。


## Related topics

- [用户](/zh-CN/build/core-features/common/user/user-toc.md)
- [GDK 中的用户身份与 XUser API](/zh-CN/build/core-features/common/user/index.md)
- [XUserFindForDevice](/zh-CN/reference/system/xuser/functions/xuserfindfordevice.md)
- [GameInputEnumerationKind](/zh-CN/reference/input/gameinput/enums/gameinputenumerationkind.md)
- [动态延迟输入](/zh-CN/build/core-features/common/input/advanced/input-synchronization.md)
