适用于 Unity 引擎的 VkQuality 插件可提供启动时间建议 图形 API(Vulkan 或 OpenGL ES),以便在特定设备上 设备。
VkQuality 建议在一组比 Unity 更加受限的设备上使用 Vulkan 引擎的默认许可名单。使用 VkQuality 即可获享 使用 Vulkan,同时将 Vulkan 的使用范围限制为具有较新图形的较新设备 驱动程序,这可以限制游戏出现驱动程序问题的风险。仅 VkQuality 因为我们仍然可以 在推荐设备上遇到驱动程序问题。VkQuality 支持自定义列表、 以便添加或移除系统推荐的设备 。
在 Unity 引擎游戏中启用 Vulkan
VkQuality 要求您的游戏同时具有 OpenGL ES 和 Vulkan 渲染程序 已在 Unity 项目设置中启用。使用自动 图形 API 选项,或手动设置图形 API。
获取适用于 Unity 引擎的 VkQuality 插件
从 GitHub 下载 VkQuality 插件。该插件 与 Unity 2021 及更高版本兼容。使用 Unity 2021 LTS 或更高版本以启用 Android 上的 Vulkan。插件包包含一个基本示例项目, 用于在启动时设置图形 API,然后显示一个设置为 设备的有效图形 API。
管理 VkQuality Vulkan 建议列表
VkQuality 中包含受支持设备的默认推荐列表。对于 有关如何使用自定义推荐列表的信息,请参阅使用自定义推荐列表 建议列表部分。
建议列表包括三类:
- Vulkan 设备许可名单
- GPU 建议许可名单
- GPU 建议拒绝列表
设备许可名单匹配
VkQuality 先会检查活跃设备是否包含在设备允许范围内
以及运行的 Android 版本和 Vulkan 驱动程序是否最低
该设备的许可名单中指定的版本。如果满足了这些条件
VkQuality 通过返回
RECOMMENDATION_VULKAN_BECAUSE_DEVICE_MATCH
枚举值。
设备在许可名单中,但运行的是 Android 版本或驱动程序
版本低于许可名单中为其指定的最低版本 (VkQuality)
通过返回 RECOMMENDATION_GLES_BECAUSE_OLD_DRIVER
来推荐 OpenGL ES。
GPU 建议一致
如果在设备许可名单中找不到匹配的设备,VkQuality 就会评估
根据 GPU 建议允许和拒绝 GPU 型号和驱动程序版本
列表。如果 GPU 型号和驱动程序版本与 GPU 中的某个条目匹配
推荐许可名单,VkQuality 通过返回
RECOMMENDATION_VULKAN_BECAUSE_PREDICTION_MATCH
枚举常量。
如果 GPU 型号和驱动程序版本与 GPU 中的条目匹配
建议拒绝名单,VkQuality 通过返回
RECOMMENDATION_GLES_BECAUSE_PREDICTION_MATCH
。
不匹配的推荐内容
如果未找到匹配项,如果 Android API 级别为
正在运行的设备不低于
建议列表。默认推荐列表的未来 API 级别为
36,表示在搭载 API 级别 36 或更高级别的不匹配设备上,VkQuality
返回 RECOMMENDATION_VULKAN_BECAUSE_FUTURE_ANDROID
枚举常量。
如果在设备许可名单或 GPU 建议列表中找不到匹配项,
并且设备的 API 级别低于 Future API 级别,即 VkQuality
通过返回 RECOMMENDATION_GLES_BECAUSE_NO_DEVICE_MATCH
来推荐 OpenGL ES。
将 VkQuality 归档文件添加到项目中
VkQuality 插件是 VkQuality-1.x.x.aar
文件,位于
已下载软件包归档的 Assets/Android/Plugins
目录。实际
.aar 文件的版本号与软件包的版本号一致
归档名称。如需安装该插件,请执行以下步骤:
- 将该 .aar 文件复制到您的
Assets/Android/Plugins
项目。(创建所需的Android
和Plugins
子目录,如果需要 不存在。)
![所需项目目录中的 VkQuality .aar 文件。](https://developer.android.google.cn/static/images/games/engines/unity/unity-vkquality-unityassets.png?authuser=9&hl=uk)
- 在 Unity Project 层次结构中选择
VkQuality-1.x.x
插件文件 在 Inspector 窗格中打开 Import Settings。请确保 已选中 Android 平台。
![图 2. VkQuality 插件平台导入设置。](https://developer.android.google.cn/static/images/games/engines/unity/unity-vkquality-unityplugin.png?authuser=9&hl=uk)
使用自定义 activity 调用 VkQuality
与典型的 Unity 引擎插件不同,必须执行 VkQuality 才能获得 图形 API 建议。然后,您可以使用 Unity 播放器命令行参数功能来设置 根据 VkQuality 建议生成的图形 API。在 Android 上,传递 命令行参数要求覆盖 UnityPlayerActivity创建一个自定义 activity。
如果您的游戏已在使用自定义 activity,请参阅将 VkQuality 添加到 现有自定义活动部分。要创建新的自定义活动,请执行以下操作: 请参阅下一部分中的向 Unity 项目添加自定义 activity。
向 Unity 引擎项目添加自定义 activity
插件中包含使用 VkQuality 的自定义 Activity 示例
软件包位于 Assets/Plugins/Android/VkQualityTestActivity.java
中。
如需自定义该文件并在游戏中使用,请按以下步骤操作:
- 将
VkQualityTestActivity.java
文件复制到Assets/Plugins/Android
目录中。 - 将其重命名为适合您游戏的名称(例如,
MyGameActivity.java
)。 - 在文本编辑器中打开该文件。
- 将类名称从
VkQualityTestActivity
更改为您为 文件(例如MyGameActivity.java
)。 - 将软件包名称从
com.google.android.games.VkQualityTest
更改为 与 Unity Project Settings 中 Package Name 字段的值一致 其他设置下的玩家类别(例如,com.mycompany.mygame
)。 - 保存并关闭该文件。
添加一个引用您的自定义 activity 的自定义清单文件,并告知 Unity 使用您的自定义清单文件:
- 从
Assets/Plugins/Android
复制AndroidManifest.xml
文件 将插件软件包的目录复制到项目的Asset/Plugins/Android
中 目录。 - 在文本编辑器中打开该文件。
- 将
activity android:name
设置的值从com.google.android.games.VkQualityTest.VkQualityTestActivity
至 您在前面的步骤中使用的软件包和 activity 名称(例如,com.mycompany.mygame.MyGameActivity
)。 - 保存并关闭该文件。
- 打开 Unity 设置窗口,然后选择 Player 设置。展开 Publishing Settings(发布设置)部分,然后选中 Custom Main Manifest(自定义主清单) 复选框。
![图 3. Unity Player 设置中的“Custom Main Manifest”选项。](https://developer.android.google.cn/static/images/games/engines/unity/unity-vkquality-unitymanifest.png?authuser=9&hl=uk)
您的项目现已设置为使用在 并根据 VkQuality 建议选择 Vulkan 或 OpenGL ES。
将 VkQuality 添加到现有自定义 activity
如果您的游戏已有用于替换默认设置的自定义 activity
UnityPlayerActivity
,通过添加
以下代码:
首先,将 VkQuality import 语句添加到顶部的导入列表中 自定义 activity 文件:
Kotlin
import com.google.android.games.vkquality.VKQuality;
Java
import com.google.android.games.vkquality.VKQuality;
接下来,在 Activity
类的正文中为
图形 API 选项:
Kotlin
companion object { private const val OVERRIDE_NONE = 0 private const val OVERRIDE_GLES = 1 private const val OVERRIDE_VULKAN = 2
Java
private static final int OVERRIDE_NONE = 0; private static final int OVERRIDE_GLES = 1; private static final int OVERRIDE_VULKAN = 2;
创建一个变量来跟踪 API 选择:
Kotlin
private var apiOverride = OVERRIDE_NONE
Java
private int apiOverride = OVERRIDE_NONE;
将以下函数添加到您的 Activity
类:
Kotlin
private fun CheckVkQuality() { val vkQuality = VKQuality(this) val startResult = vkQuality.StartVkQuality("") if (startResult == VKQuality.INIT_SUCCESS) { // In the current release, we can assume GetVkQuality is // ready as soon as StartVkQuality has returned success. val getResult = vkQuality.GetVkQuality() LogVkQualityResult(getResult) apiOverride = when (getResult) { VKQuality.RECOMMENDATION_VULKAN_BECAUSE_DEVICE_MATCH, VKQuality.RECOMMENDATION_VULKAN_BECAUSE_PREDICTION_MATCH, VKQuality.RECOMMENDATION_VULKAN_BECAUSE_FUTURE_ANDROID -> OVERRIDE_VULKAN VKQuality.RECOMMENDATION_GLES_BECAUSE_OLD_DEVICE, VKQuality.RECOMMENDATION_GLES_BECAUSE_OLD_DRIVER, VKQuality.RECOMMENDATION_GLES_BECAUSE_NO_DEVICE_MATCH, VKQuality.RECOMMENDATION_GLES_BECAUSE_PREDICTION_MATCH -> OVERRIDE_GLES else -> OVERRIDE_GLES } vkQuality.StopVkQuality() } else { Log.e("VKQUALITY", "VkQuality start failed with result: $startResult") } }
Java
private void CheckVkQuality() { VKQuality vkQuality = new VKQuality(this); // An empty string specifies use of the default // built-in device list file. int startResult = vkQuality.StartVkQuality(""); if (startResult == VKQuality.INIT_SUCCESS) { // In the current release, we can assume GetVkQuality is // ready as soon as StartVkQuality has returned success. int getResult = vkQuality.GetVkQuality(); switch (getResult) { case VKQuality.RECOMMENDATION_VULKAN_BECAUSE_DEVICE_MATCH: case VKQuality.RECOMMENDATION_VULKAN_BECAUSE_PREDICTION_MATCH: case VKQuality.RECOMMENDATION_VULKAN_BECAUSE_FUTURE_ANDROID: apiOverride = OVERRIDE_VULKAN; break; case VKQuality.RECOMMENDATION_GLES_BECAUSE_OLD_DEVICE: case VKQuality.RECOMMENDATION_GLES_BECAUSE_OLD_DRIVER: case VKQuality.RECOMMENDATION_GLES_BECAUSE_NO_DEVICE_MATCH: case VKQuality.RECOMMENDATION_GLES_BECAUSE_PREDICTION_MATCH: default: apiOverride = OVERRIDE_GLES; break; } vkQuality.StopVkQuality(); } else { Log.e("VKQUALITY", "VkQuality start failed with result: " + startResult); } }
从 onCreate()
替换项的顶部调用 CheckVkQuality
函数
函数:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { CheckVkQuality() super.onCreate(savedInstanceState) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { CheckVkQuality(); super.onCreate(savedInstanceState); }
最后,添加 updateUnityCommandLineArguments()
函数的替换项。
该函数使用 apiOverride
的值将命令行参数传递给
Unity 引擎,用于指定要使用的图形 API:
Kotlin
override fun updateUnityCommandLineArguments(cmdLine: String): String { if (apiOverride == OVERRIDE_VULKAN) { Log.i("VKQUALITY", "Passing -force-vulkan") return appendCommandLineArgument(cmdLine, "-force-vulkan") } else if (apiOverride == OVERRIDE_GLES) { Log.i("VKQUALITY", "Passing -force-gles") return appendCommandLineArgument(cmdLine, "-force-gles") } Log.i("VKQUALITY", "No override passed") // let Unity pick the Graphics API based on PlayerSettings return cmdLine } private fun appendCommandLineArgument(cmdLine: String, arg: String?): String { return if (arg == null || arg.isEmpty()) cmdLine else if (cmdLine == null || cmdLine.isEmpty()) arg else "$cmdLine $arg" }
Java
@Override protected String updateUnityCommandLineArguments(String cmdLine) { if (apiOverride == OVERRIDE_VULKAN) { Log.i("VKQUALITY", "Passing -force-vulkan"); return appendCommandLineArgument(cmdLine, "-force-vulkan"); } else if (apiOverride == OVERRIDE_GLES) { Log.i("VKQUALITY", "Passing -force-gles"); return appendCommandLineArgument(cmdLine, "-force-gles"); } Log.i("VKQUALITY", "No override passed"); // let Unity pick the Graphics API based on PlayerSettings return cmdLine; } private String appendCommandLineArgument(String cmdLine, String arg) { if (arg == null || arg.isEmpty()) return cmdLine; else if (cmdLine == null || cmdLine.isEmpty()) return arg; else return cmdLine + " " + arg; }
您的自定义 activity 现在会在启动时调用 VkQuality 并选择 Vulkan 或 OpenGL 根据 VkQuality 建议的 ES。
使用自定义推荐列表
通过传递文件名来指定自定义推荐列表文件
将包含列表的列表传递给 StartVkQuality()
,而不是传递空字符串:
Kotlin
val startResult = vkQuality.StartVkQuality("CUSTOM_FILE_NAME.vkq")
Java
int startResult = vkQuality.StartVkQuality("CUSTOM_FILE_NAME.vkq");
VkQuality 先在应用的内部存储空间中查找该文件
目录。如果文件不在内部存储空间中,VkQuality 会尝试加载
文件。如果文件不在上述任一位置
VkQuality 会返回 ERROR_MISSING_DATA_FILE
枚举值。
如需创建自定义推荐列表文件,请使用 VkQuality List Editor 该工具位于 GitHub 代码库中有关 README 文件。