HarmonyOS 游戏场景感知:用 C++ 实现游戏APP与系统交互
·
什么是游戏场景感知
上一篇我们介绍了用 ArkTS 实现游戏场景感知,这篇来看看用 C++ 怎么做。C++ 版本功能更强大,可以获取更详细的设备信息。
简单回顾一下:游戏场景感知让游戏可以和系统"对话"。游戏告诉系统"我现在在做什么",系统告诉游戏"设备现在状态怎么样"。这样双方就能更好地配合,既保证游戏流畅,又不让手机过热。
环境搭建
硬件要求
- 设备类型:华为手机、平板和 PC/2in1
- HarmonyOS 系统:HarmonyOS 5.0.2 Beta1 及以上
软件要求
- DevEco Studio 版本:DevEco Studio 5.0.2 Beta1 及以上
- HarmonyOS SDK 版本:HarmonyOS 5.0.2 Beta1 SDK 及以上
搭建步骤
- 安装 DevEco Studio:去华为开发者官网下载安装
- 配置开发环境:确保网络环境正常
- 设备调试:使用真机进行调试
项目结构
├── entry/src/main
│ ├── cpp
│ │ ├── CMakeLists.txt // 编译配置
│ │ ├── init.cpp // 初始化
│ │ ├── thermallevel_callback.cpp // 温度回调
│ │ ├── updategameinfo.cpp // 更新场景信息
│ │ ├── query_gpuinfo.cpp // 查询GPU信息
│ │ └── query_thermalinfo.cpp // 查询温度信息
│ ├── ets
│ │ ├── entryability
│ │ │ └── EntryAbility.ets
│ │ └── pages
│ │ └── Index.ets
│ └── resources
整体流程概览
下面是 C++ 版本游戏场景感知的整体开发流程:
下面是温度变化回调的处理流程:
第一步:配置 CMakeLists.txt
target_include_directories(entry PUBLIC ${HMOS_SDK_NATIVE}/sysroot/usr/include)
target_link_directories(entry PUBLIC ${HMOS_SDK_NATIVE}/sysroot/usr/lib/aarch64-linux-ohos)
target_link_libraries(entry PUBLIC libgame_performance.z.so)
链接 game_performance 动态库,并设置头文件和库文件的搜索路径。
第二步:导入头文件
#include <GameServiceKit/game_performance.h>
导入 Game Service Kit 的 C++ 头文件。
第三步:初始化场景感知
int32_t Init() {
// 创建初始化参数。
GamePerformance_InitParameters *initParameters = NULL;
HMS_GamePerformance_CreateInitParameters(&initParameters);
// 设置应用版本。
GamePerformance_ErrorCode appVersionSetCode =
HMS_GamePerformance_InitParameters_SetAppVersion(initParameters, "1.0");
if (appVersionSetCode != GAME_PERFORMANCE_SUCCESS) {
// 错误处理
}
// 设置包名。
HMS_GamePerformance_InitParameters_SetBundleName(initParameters, "com.example.gameperformancedemoforc");
// 初始化。
GamePerformance_ErrorCode ret = HMS_GamePerformance_Init(initParameters);
// 释放内存。
HMS_GamePerformance_DestroyInitParameters(&initParameters);
int32_t code = static_cast<int32_t>(ret);
return code;
}
初始化步骤:
- 创建参数对象:
HMS_GamePerformance_CreateInitParameters创建一个参数对象 - 设置参数:设置应用版本和包名
- 初始化:
HMS_GamePerformance_Init执行初始化 - 释放内存:
HMS_GamePerformance_DestroyInitParameters释放参数对象
和 ArkTS 版本相比,C++ 版本需要手动管理内存,创建和销毁都要显式调用。
第四步:注册温度变化回调
// 定义回调函数
static void onThermalLevelChanged(GamePerformance_DeviceInfo *deviceInfo, void *userData) {
(void) userData;
// 获取 GPU 信息。
GamePerformance_GpuInfo *gpuInfo = NULL;
HMS_GamePerformance_DeviceInfo_GetGpuInfo(deviceInfo, &gpuInfo);
int32_t gpuloadLevel = -1;
int32_t vertexLevel = -1;
int32_t fragmentLoadLevel = -1;
int32_t bandwidthLoadLevel = -1;
int32_t textureLoadLevel = -1;
int32_t currentFrequency = -1;
HMS_GamePerformance_GpuInfo_GetGpuLoadLevel(gpuInfo, &gpuloadLevel);
HMS_GamePerformance_GpuInfo_GetVertexLoadLevel(gpuInfo, &vertexLevel);
HMS_GamePerformance_GpuInfo_GetFragmentLoadLevel(gpuInfo, &fragmentLoadLevel);
HMS_GamePerformance_GpuInfo_GetBandwidthLoadLevel(gpuInfo, &bandwidthLoadLevel);
HMS_GamePerformance_GpuInfo_GetTextureLoadLevel(gpuInfo, &textureLoadLevel);
HMS_GamePerformance_GpuInfo_GetCurrentFrequency(gpuInfo, ¤tFrequency);
回调函数会在设备状态变化时被调用。这里获取了 GPU 的详细信息:
gpuloadLevel:GPU 整体负载等级vertexLevel:顶点处理负载fragmentLoadLevel:片元处理负载bandwidthLoadLevel:带宽负载textureLoadLevel:纹理负载currentFrequency:当前频率
// 获取温度信息。
GamePerformance_ThermalInfo *thermalInfo = NULL;
HMS_GamePerformance_DeviceInfo_GetThermalInfo(deviceInfo, &thermalInfo);
int32_t margin = INT32_MIN;
int32_t trend = INT32_MIN;
int32_t level = -1;
HMS_GamePerformance_ThermalInfo_GetThermalMargin(thermalInfo, &margin);
HMS_GamePerformance_ThermalInfo_GetThermalTrend(thermalInfo, &trend);
HMS_GamePerformance_ThermalInfo_GetThermalLevel(thermalInfo, &level);
// 释放内存。
HMS_GamePerformance_DestroyGpuInfo(&gpuInfo);
HMS_GamePerformance_DestroyThermalInfo(&thermalInfo);
}
获取温度信息:
margin:温度余量,表示距离温度上限还有多少trend:温度趋势,表示温度在升高还是降低level:温度等级
int32_t RegisterThermalLevelChangedCallback() {
// 订阅设备信息类型。
size_t size = 2;
GamePerformance_DeviceInfoType *types[] = {
new GamePerformance_DeviceInfoType(GAME_PERFORMANCE_DEVICEINFO_TYPE_GPU),
new GamePerformance_DeviceInfoType(GAME_PERFORMANCE_DEVICEINFO_TYPE_THERMAL)};
void *userData = (void *)"mydata";
GamePerformance_ErrorCode ret =
HMS_GamePerformance_RegisterThermalLevelChangedCallback(types, size, onThermalLevelChanged, userData);
int32_t code = static_cast<int32_t>(ret);
return code;
}
注册回调时,指定要订阅的设备信息类型:
GAME_PERFORMANCE_DEVICEINFO_TYPE_GPU:GPU 信息GAME_PERFORMANCE_DEVICEINFO_TYPE_THERMAL:温度信息
第五步:取消注册温度变化回调
int32_t UnregisterThermalLevelChangedCallback() {
GamePerformance_ErrorCode ret = HMS_GamePerformance_UnregisterThermalLevelChangedCallback(onThermalLevelChanged);
int32_t code = static_cast<int32_t>(ret);
return code;
}
int32_t UnregisterAllThermalLevelChangedCallbacks() {
GamePerformance_ErrorCode ret = HMS_GamePerformance_UnregisterAllThermalLevelChangedCallbacks();
int32_t code = static_cast<int32_t>(ret);
return code;
}
有两种取消方式:
UnregisterThermalLevelChangedCallback:取消指定的回调UnregisterAllThermalLevelChangedCallbacks:取消所有回调
第六步:上报游戏场景信息
int32_t UpdateSceneInfo() {
GamePerformance_SceneInfo *sceneInfo = NULL;
HMS_GamePerformance_CreateSceneInfo(&sceneInfo);
// 设置必填字段。
HMS_GamePerformance_SceneInfo_SetSceneID(sceneInfo, 1);
HMS_GamePerformance_SceneInfo_SetImportanceLevel(sceneInfo, GAME_PERFORMANCE_SIL_LEVEL1);
// 设置可选字段。
HMS_GamePerformance_SceneInfo_SetDescription(sceneInfo, "this is description of scene");
HMS_GamePerformance_SceneInfo_SetSubSceneID(sceneInfo, "20101020304");
HMS_GamePerformance_SceneInfo_SetSubDescription(sceneInfo, "this is description of subscene");
HMS_GamePerformance_SceneInfo_SetSceneFrequency(sceneInfo, 2);
HMS_GamePerformance_SceneInfo_SetSceneTime(sceneInfo, 15);
创建场景信息对象,设置各种参数:
SceneID:场景 IDImportanceLevel:重要性等级Description:场景描述SubSceneID:子场景 IDSceneFrequency:场景刷新频率SceneTime:场景持续时间
// 设置推荐的硬件等级。
HMS_GamePerformance_SceneInfo_SetRecommendedCpuLevel(sceneInfo, GAME_PERFORMANCE_CPU_LEVEL_HIGH);
HMS_GamePerformance_SceneInfo_SetRecommendedGpuLevel(sceneInfo, GAME_PERFORMANCE_GPU_LEVEL_HIGH);
HMS_GamePerformance_SceneInfo_SetRecommendedDdrLevel(sceneInfo, GAME_PERFORMANCE_DDR_LEVEL_HIGH);
设置推荐的硬件等级,告诉系统这个场景需要什么样的硬件资源。
// 设置渲染信息。
HMS_GamePerformance_SceneInfo_SetKeyThread(sceneInfo, "render");
HMS_GamePerformance_SceneInfo_SetDrawCallCount(sceneInfo, 100);
HMS_GamePerformance_SceneInfo_SetVertexCount(sceneInfo, 100);
HMS_GamePerformance_SceneInfo_SetTriangleCount(sceneInfo, 100);
HMS_GamePerformance_SceneInfo_SetShaderCount(sceneInfo, 100);
HMS_GamePerformance_SceneInfo_SetTextureCount(sceneInfo, 100);
HMS_GamePerformance_SceneInfo_SetMeshCount(sceneInfo, 100);
HMS_GamePerformance_SceneInfo_SetChannelCount(sceneInfo, 100);
HMS_GamePerformance_SceneInfo_SetParticipantCount(sceneInfo, 5);
// 上报场景信息。
GamePerformance_ErrorCode ret = HMS_GamePerformance_UpdateSceneInfo(sceneInfo);
// 释放内存。
HMS_GamePerformance_DestroySceneInfo(&sceneInfo);
int32_t code = static_cast<int32_t>(ret);
return code;
}
设置渲染相关的详细信息,这些信息可以帮助系统更好地理解游戏的负载情况。
第七步:查询 GPU 信息
int32_t QueryGpuInfo() {
GamePerformance_GpuInfo *gpuInfo = NULL;
GamePerformance_ErrorCode ret = HMS_GamePerformance_QueryGpuInfo(&gpuInfo);
int32_t gpuloadLevel = -1;
int32_t bandwidth = -1;
int32_t currentFrequency = -1;
int32_t fragmentLoadLevel = -1;
int32_t textureLoadLevel = -1;
int32_t vertexLoadLevel = -1;
HMS_GamePerformance_GpuInfo_GetGpuLoadLevel(gpuInfo, &gpuloadLevel);
HMS_GamePerformance_GpuInfo_GetBandwidthLoadLevel(gpuInfo, &bandwidth);
HMS_GamePerformance_GpuInfo_GetCurrentFrequency(gpuInfo, ¤tFrequency);
HMS_GamePerformance_GpuInfo_GetFragmentLoadLevel(gpuInfo, &fragmentLoadLevel);
HMS_GamePerformance_GpuInfo_GetTextureLoadLevel(gpuInfo, &textureLoadLevel);
HMS_GamePerformance_GpuInfo_GetVertexLoadLevel(gpuInfo, &vertexLoadLevel);
HMS_GamePerformance_DestroyGpuInfo(&gpuInfo);
int32_t code = static_cast<int32_t>(ret);
return code;
}
主动查询 GPU 信息,获取当前的负载和频率状态。
第八步:查询温度信息
int32_t QueryThermalInfo() {
GamePerformance_ThermalInfo *thermalInfo = NULL;
GamePerformance_ThermalInfoQueryParameters *parameters = NULL;
// 创建查询参数。
HMS_GamePerformance_CreateThermalInfoQueryParameters(¶meters);
// 设置是否需要预测温度趋势。
HMS_GamePerformance_ThermalInfoQueryParameters_SetNeedsPrediction(parameters, true);
// 设置目标温度等级。
HMS_GamePerformance_ThermalInfoQueryParameters_SetTargetThermalLevel(parameters, 4);
// 查询温度信息。
GamePerformance_ErrorCode ret = HMS_GamePerformance_QueryThermalInfo(parameters, &thermalInfo);
int32_t margin = INT32_MIN;
int32_t trend = INT32_MIN;
int32_t level = -1;
HMS_GamePerformance_ThermalInfo_GetThermalLevel(thermalInfo, &level);
HMS_GamePerformance_ThermalInfo_GetThermalMargin(thermalInfo, &margin);
HMS_GamePerformance_ThermalInfo_GetThermalTrend(thermalInfo, &trend);
// 释放内存。
HMS_GamePerformance_DestroyThermalInfo(&thermalInfo);
HMS_GamePerformance_DestroyThermalInfoQueryParameters(¶meters);
int32_t code = static_cast<int32_t>(ret);
return code;
}
查询温度信息时,可以设置预测参数:
SetNeedsPrediction:是否需要预测温度趋势SetTargetThermalLevel:目标温度等级,用于预测
C++ 版和 ArkTS 版的区别
| 方面 | C++ 版 | ArkTS 版 |
|---|---|---|
| 信息详细程度 | 更详细,有 GPU 负载、顶点/片元负载等 | 较简单,主要是温度等级 |
| 内存管理 | 手动管理,需要创建和销毁对象 | 自动管理 |
| 开发难度 | 较高 | 较低 |
| 性能 | 更好 | 一般 |
| 使用场景 | 复杂游戏、性能要求高 | 简单游戏、快速开发 |
适用场景
游戏场景感知特别适合以下场景:
- 大型 3D 游戏:需要详细的 GPU 信息来优化渲染
- 竞技游戏:对帧率要求高,需要实时调整性能
- 长时间游戏:需要防止手机过热
- 跨平台游戏:需要适配不同设备的性能
注意事项
- 内存管理:C++ 版本需要手动管理内存,创建的对象都要销毁
- 回调函数:回调函数要轻量,不要做耗时操作
- 订阅类型:注册回调时要指定订阅的设备信息类型
- 错误处理:每个接口调用都要检查返回值
- 线程安全:回调可能在非主线程调用,要注意线程安全
总结
C++ 版本的游戏场景感知功能更强大,核心流程:
- 配置 CMakeLists.txt,链接 game_performance 库
- 初始化场景感知服务
- 注册温度变化回调,监听设备状态
- 上报游戏场景信息,让系统优化资源分配
- 主动查询 GPU 和温度信息
- 不需要时取消注册回调
如果你的游戏对性能要求很高,需要详细的设备信息来优化,C++ 版本是更好的选择。
更多推荐

所有评论(0)