> ## 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.

# 游戏串流延迟补偿深入探讨

> 游戏串流延迟补偿深入探讨

<Info>**部分弃用。** 本文中所述的帧关联技术依赖 `XGameStreamingGetAssociatedFrame` 和 `XGameStreamingGetLastFrameDisplayed`，这些函数**自 2604 GDK 版本起被弃用**，并将在未来版本中被移除。通用延迟测量 API `XGameStreamingGetStreamAddedLatency` 仍然可用。有关不依赖帧关联的延迟感知技术，请参阅 [游戏串流延迟测量](/build/core-features/common/game-streaming/game-streaming-latency-measurement)。</Info>

使用本主题来确定使用 XBOX 游戏串流游玩时游戏的延迟补偿。

电子游戏在处理快速动作时可能存在对时间敏感的输入处理。想象一个平台跳跃游戏，用户的角色站在一条通向悬崖的移动传送带上（如图 1 所示）。

用户必须在合适的时机跳跃 - 太早会错过下一个平台，太晚则会在跳跃前坠落。游戏串流中的网络延迟意味着当用户看到自己的角色处于合适的跳跃位置时，从 XBOX 服务的角度来看，角色可能已经从末端坠落了。

当游戏最终通过网络接收到按钮按下时，即使用户从他们的角度按下按钮时视频帧正确，游戏也可能记录一次坠落。

**图 1. 显示带有传送带上角色的平台跳跃游戏示例。**

<img src="https://mintcdn.com/microsoft-4404708b/UZTRJSf0emX1fheE/images/gdk/features/common/game-streaming-platformer-diagram.png?fit=max&auto=format&n=UZTRJSf0emX1fheE&q=85&s=d507fe0c9617a01e1c026279eacf25a8" alt="带有传送带上角色的平台跳跃游戏屏幕截图" width="451" height="133" data-path="images/gdk/features/common/game-streaming-platformer-diagram.png" />

## 延迟补偿

为了补偿如图 1 所示示例中的延迟，游戏会保留其先前状态的记录。

当用户按下跳跃按钮时，游戏会搜索游戏中的该时点，以确定用户是否从他们的角度在正确的时刻按下了按钮。

正确的延迟补偿关键在于知道应向过去搜索多远。XBOX 游戏串流 API 为此提供了几种选项。

## 平均延迟

对于某些情景而言，最简单但最不精确的方法是使用平均延迟。

[XGameStreamingGetStreamAddedLatency](/reference/system/xgamestreaming/functions/xgamestreaminggetstreamaddedlatency) API 返回由串流带来的最近平均延迟。该平均值分为输入延迟和输出延迟。

输入延迟是用户输入被服务器接收所需的时间，输出延迟是游戏渲染的视频帧被客户端设备接收和处理所需的时间。

对于基于时间的操作，游戏可以使用此平均值作为动作发生时点的估算。然而，网络延迟可能会有所变化，甚至逐帧变化，因此这种方法并不精确。此外，串流增加的延迟测量不包括非串流部分的延迟，例如游戏运行模拟和渲染所需的时间。

## 带输入的帧令牌

[XGameStreamingGetAssociatedFrame](/reference/system/xgamestreaming/functions/xgamestreaminggetassociatedframe) API 通过提供有关用户按下按钮（或更改任何其他输入）时所看到的游戏状态的精确信息，帮助解决此问题。

当一帧开始时，使用 Microsoft Game Development Kit (GDK) 的游戏会调用 `ID3D12Device::WaitFrameEventX` 并接收一个 `D3D12XBOX_FRAME_PIPELINE_TOKEN`。您可以使用 `D3D12XBOX_FRAME_PIPELINE_TOKEN` 作为键，将当前状态保存到您选择的数据结构（如哈希图）中以备后用。当帧完成时，游戏使用该令牌调用 `PresentX`。

`PresentX` 确保该令牌与匹配的视频帧一起自动发送到游戏串流客户端。

发送到服务器的输入伴随有当前显示在客户端上的帧的令牌。当游戏接收到 `IGameInputReading` 时，您可以将其传递给 `XGameStreamingGetAssociatedFrame` API 来取回该令牌。您可以使用它来查找先前的状态并根据该存储状态处理输入。

<Note>如果输入没有变化（因为用户没有触摸控制器，或因为他们只是按住按钮），则不会有新的令牌。</Note>

## 无输入的帧令牌

在某些情况下，即使用户的输入没有变化，您也必须知道用户最近看到了什么。回到图 1 所示示例，当角色到达传送带末端时，他们会坠落。游戏的部分挑战和公平性在于在这些时间窗口内做出反应。

理想情况下，串流用户应有与非串流用户相同的反应时间。由于延迟，窗口的结束时间应该被推后，以便在窗口末端接收到的输入被接受。

为此，游戏可以在没有按下按钮的情况下使用延迟令牌。如果无操作的输入读取与窗口末端的状态相匹配，则用户未能做出反应，游戏可以公平地对其进行惩罚。

[XGameStreamingGetLastFrameDisplayed](/reference/system/xgamestreaming/functions/xgamestreaminggetlastframedisplayed) API 返回串流客户端最近显示的帧的 `D3D12XBOX_FRAME_PIPELINE_TOKEN`。由于它在不断更新，您可以随时调用它并查看用户是否已看到动画的结尾。

<Note>可以以与 `XGameStreamingGetAssociatedFrame` 相同的方式使用 `XGameStreamingGetLastFrameDisplayed`。我们建议在处理输入时使用 `XGameStreamingGetAssociatedFrame`，因为它返回该输入发生时屏幕上的令牌。如果时间过得更长，`XGameStreamingGetLastFrameDisplayed` 可能会返回更新帧的令牌。</Note>

## 更多情景

使用上一节中的三个 API 可以补偿各种情景下的延迟。以下部分基于常见的多人延迟补偿技术提供更多示例。

### 移动

移动角色、镜头或瞄准可分为两类。

#### 具有离散结果的移动

当用户移动到碰撞或瞄准并开火时，游戏必须对移动的结果做出用户可见的决定。

对于这些情况，通常会推迟这个二元决策，直到游戏收到与需要做出决策的帧相关联的输入。对于诸如碰撞或从悬崖坠落之类的事情，游戏可能需要在等待时播放某个动画。

例如，在游戏接收实际输入所需的时间内，用户可能会穿透物体，或者悬浮或跳过悬崖。

#### 一般移动

一般移动是指任何导航或瞄准，但对于诸如驾驶等累积移动比某一帧上发生的事情更重要的情况来说至关重要。

##### 输入预测

游戏可以使用输入的历史，根据用户看到他们提供输入的帧后经过的时间向前预测。例如，如果拇指摇杆的坐标为 0.5，并且每帧平均进展 0.1，而延迟令牌为 3 帧前，游戏可以将其视为处于 0.8。

当然，如果用户改变速度和方向，这可能导致预测错误。为了纳入用户的实际输入，游戏可以保留先前预测状态的缓冲区。当该状态的实际输入出现时，游戏可以从该状态使用真实输入重新运行其模拟并修正可见状态。

如上所述，游戏应等待到已知实际输入后再触发任何结果。在延迟较高的连接上，这可能导致可见的 “弹跳”，游戏可能希望提供平滑处理或其他方式来遮盖错误预测。

采用此策略时，渲染的帧到达客户端所需的时间会更多。游戏可能希望进一步按平均输出延迟进行预测，以将用户的视图与服务器的模拟同步。这在多人游戏中更为重要，因为服务器的模拟速度可能由外部多人游戏服务器控制。

##### 游戏专属预测

游戏可能比通过投影输入历史更善于猜测用户的行为。这可以从简单的启发式方法（如 2D 平台跳跃游戏角色向右移动）到基于用户历史的机器学习。与输入预测一样，游戏可以保留预测缓冲区，并在实际输入到达时重新运行其模拟。

### 触控轨迹跟踪

使用原生触控的游戏可能会在用户手指下方放置光标或准心。在较高延迟下，用户会注意到光标落后于移动的手指。如本主题一般移动部分所述，游戏可能会预测移动触控输入的方向和速度，以保持光标大致在移动的手指下方。

### 多人游戏

在 XBOX 游戏串流上运行的多人游戏的一个优点是，用户的 XBOX 服务器可能位于同一 Azure 数据中心。如果游戏的多人服务器也在该 Azure 区域，则 XBOX 主机与多人服务器之间的延迟不到一毫秒。然而，用户的客户端设备距离更远。

多人游戏通常有处理游戏到多人服务器延迟的策略。这些策略通常包括来自多人服务器的时间戳或帧计数器。

通过将这些时间戳和计数器与帧令牌关联，多人游戏可以将串流包含在其延迟计算中。这有助于多人游戏对串流用户的感觉合理，并在串流用户和非串流用户之间创造平等的条件。

## 参考 API 文档

* [XGameStreaming（API 内容）](/reference/system/xgamestreaming/xgamestreaming_members)
  * 函数
    * [XGameStreamingGetStreamAddedLatency](/reference/system/xgamestreaming/functions/xgamestreaminggetstreamaddedlatency)
    * [XGameStreamingGetAssociatedFrame](/reference/system/xgamestreaming/functions/xgamestreaminggetassociatedframe)
    * [XGameStreamingGetLastFrameDisplayed](/reference/system/xgamestreaming/functions/xgamestreaminggetlastframedisplayed)

## 另请参阅

[游戏串流延迟补偿概述](/build/core-features/common/game-streaming/game-streaming-latency-compensation-overview)
[游戏串流延迟测量](/build/core-features/common/game-streaming/game-streaming-latency-measurement)
[在测试游戏时模拟延迟](/build/core-features/common/game-streaming/game-streaming-simulate-latency-while-testing)
[XGameStreaming（API 内容）](/reference/system/xgamestreaming/xgamestreaming_members#Latency)


## Related topics

- [游戏串流延迟测量](/zh-CN/build/core-features/common/game-streaming/game-streaming-latency-measurement.md)
- [游戏串流延迟补偿概述](/zh-CN/build/core-features/common/game-streaming/game-streaming-latency-compensation-overview.md)
- [XGameStreamingGetAssociatedFrame](/zh-CN/reference/system/xgamestreaming/functions/xgamestreaminggetassociatedframe.md)
- [XGameStreamingGetLastFrameDisplayed](/zh-CN/reference/system/xgamestreaming/functions/xgamestreaminggetlastframedisplayed.md)
- [XGameStreamingGetStreamAddedLatency](/zh-CN/reference/system/xgamestreaming/functions/xgamestreaminggetstreamaddedlatency.md)
