流式安装:状态
当正在安装和用户正在玩游戏时,游戏必须跟踪支持玩游戏所需的内容和 检查是否已安装所需的内容。 游戏可以使用系统 API 查询硬盘上区块的状态以及下载内容的进度。
如果用户尝试进入的游戏部分需要的内容尚未安装,游戏将通过显示一个对话框或进度栏来通知用户,此时它应沟通安装的进度。 此外,游戏应始终为用户提供离开进度屏幕的选项 — 理想情况下,让用户在安装时体验内容。 以下是一个示例。
在玩射击游戏的单人游戏活动时,用户可以直接清楚用于支持活动的下一领域的内容尚未安装。 良好的用户体验是显示进度栏,显示内容获取的状态以及加入多人游戏的选项。 通过将多人游戏内容的子集作为启动游戏所需数据的一部分,将启用此选项。
游戏可以监视并验证安装,并且它可以在安装完成后收到提醒。 您可以监视整个包的安装或包中区块子集的安装。 要创建安装监视器,请使用 XPackageCreateInstallationMonitor。 指定监视器适用于以下情况之一:
- 某些区块集(通过将选择器指定为参数)
- 整个包(通过指定零个选择器)
创建安装监视器后,为以下其中一个目的注册处理程序:
- 处理安装进度已更改事件(通过使用 XPackageRegisterInstallationProgressChanged)
- 处理包已安装事件(使用 XPackageRegisterPackageInstalled)
包已安装事件指示整个包已完成安装。 通过进度已更改事件,您可以监视安装进度。 请注意,进度已更改事件也表示完成安装的时间,因此,如果您已注册进度已更改处理程序,则不需要注册包已安装处理程序。 以下是一个示例。
游戏已实现启动标记,因此它可以在完全安装之前运行。 游戏将需要了解安装哪些部分以及不安装哪些部分。 要向用户显示可用的赛道,游戏需要知道与具有特定赛道名称的比赛赛道相关联的区块何时安装。
class GameTrackMonitor
{
public:
HRESULT StartMonitoring(XTaskQueueHandle queue, const char* trackName)
{
char id[PACKAGE_IDENTIFIER_MAX_LENGTH];
XPackageChunkSelector selector;
selector.type = XPackageChunkSelectorType::Tag;
selector.tag = trackName;
RETURN_IF_FAILED(XPackageGetCurrentProcessPackageIdentifier(_countof(id), id));
XPackageInstallationMonitorHandle monitor;
RETURN_IF_FAILED(XPackageCreateInstallationMonitor(
id, // Identity to monitor.
1, // Number of selectors.
&selector, // Selectors.
1000, // Resolution of monitor in ms.
queue, // Queue where updates are performed.
&monitor));
XTaskQueueRegistrationToken token;
HRESULT hr = XPackageRegisterInstallationProgressChanged(
monitor,
this,
[](void *context, XPackageInstallationMonitorHandle monitor)
{
GameTrackMonitor* pthis = static_cast<GameTrackMonitor*>(context);
XPackageInstallationProgress progress;
XPackageGetInstallationProgress(monitor, &progress);
pthis->DrawProgress(progress);
if (progress.completed)
{
pthis->TrackReady();
XPackageCloseInstallationMonitorHandle(monitor);
}
}, &token);
if (FAILED(hr))
{
XPackageCloseInstallationMonitorHandle(monitor);
}
return hr;
}
private:
void DrawProgress(const XPackageInstallationProgress& progress)
{
// ...
}
void TrackReady()
{
// ...
}
};