针对 Unity 引擎的 VkQuality 插件提供了在特定设备上为你的游戏使用图形 API(Vulkan 或 OpenGL ES)的启动时建议。
VkQuality 在比 Unity 引擎的默认允许列表更严格的设备集上推荐 Vulkan。使用 VkQuality 可以获得 Vulkan 的性能优势,同时将 Vulkan 的使用限制在具有较新图形驱动程序的较新设备上,这可以限制你的游戏暴露于驱动程序问题。VkQuality 仅提供质量建议,不提供保证,因为它仍然有可能在推荐的设备上遇到驱动程序问题。VkQuality 支持自定义列表,这使你能够为你的游戏添加或删除设备建议。
在你的 Unity 引擎游戏中启用 Vulkan
VkQuality 要求你的游戏在 Unity 项目设置中同时启用 OpenGL ES 和 Vulkan 渲染器。使用 自动图形 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
枚举值来推荐 Vulkan。
如果设备在允许列表中,但运行的 Android 版本或驱动程序版本低于为其在允许列表中指定的最低版本,VkQuality 会通过返回 RECOMMENDATION_GLES_BECAUSE_OLD_DRIVER
来推荐 OpenGL ES。
GPU 建议匹配
如果没有在设备允许列表中找到设备匹配,VkQuality 会根据 GPU 模型和驱动程序版本评估 GPU 建议允许和拒绝列表。如果 GPU 模型和驱动程序版本与 GPU 建议允许列表中的条目匹配,VkQuality 会通过返回 RECOMMENDATION_VULKAN_BECAUSE_PREDICTION_MATCH
枚举常量来推荐 Vulkan。
如果 GPU 模型和驱动程序版本与 GPU 建议拒绝列表中的条目匹配,VkQuality 会通过返回 RECOMMENDATION_GLES_BECAUSE_PREDICTION_MATCH
来推荐 OpenGL ES。
没有匹配的建议
如果没有找到匹配项,如果运行设备的 Android API 级别等于或高于建议列表中的未来 API 级别,VkQuality 会推荐 Vulkan。默认建议列表的未来 API 级别为 36,这意味着在运行 API 级别 36 或更高版本的未匹配设备上,VkQuality 会返回 RECOMMENDATION_VULKAN_BECAUSE_FUTURE_ANDROID
枚举常量。
如果没有在设备允许列表或 GPU 建议列表中找到匹配项,并且设备的 API 级别低于未来 API 级别,VkQuality 会通过返回 RECOMMENDATION_GLES_BECAUSE_NO_DEVICE_MATCH
来推荐 OpenGL ES。
将 VkQuality 存档文件添加到你的项目
VkQuality 插件是位于下载的包存档的 Assets/Android/Plugins
目录中的 VkQuality-1.x.x.aar
文件。实际的 .aar 文件版本号与包存档名称的版本号匹配。要安装插件,请执行以下步骤
- 将 .aar 文件复制到项目的
Assets/Android/Plugins
目录。(如果不存在,请创建所需的Android
和Plugins
子目录。)
- 在 Unity 项目层次结构中选择
VkQuality-1.x.x
插件文件以在 检查器窗格中显示其 导入设置。确保选中 Android 平台。
使用自定义活动调用 VkQuality
与典型的 Unity 引擎插件不同,必须执行 VkQuality 以在初始化 Unity 引擎之前获得图形 API 建议。然后,你可以使用 Unity 播放器命令行参数 功能根据 VkQuality 建议设置图形 API。在 Android 上,传递命令行参数需要通过 创建自定义活动 来覆盖 UnityPlayerActivity 的默认行为。
如果你的游戏已经在使用自定义活动,请参阅 将 VkQuality 添加到现有自定义活动 部分。要为你的游戏创建一个新的自定义活动,请参阅 将自定义活动添加到你的 Unity 项目,该部分将在下面介绍。
将自定义活动添加到你的 Unity 引擎项目
一个使用 VkQuality 的示例自定义活动包含在 插件包 中的 Assets/Plugins/Android/VkQualityTestActivity.java
中。要自定义该文件并在你的游戏中使用它,请执行以下步骤
- 将
VkQualityTestActivity.java
文件复制到你的Assets/Plugins/Android
目录。 - 将其重命名为适合你的游戏的名称(例如,
MyGameActivity.java
)。 - 在文本编辑器中打开该文件。
- 将类名从
VkQualityTestActivity
更改为你给文件起的名称(例如,MyGameActivity.java
)。 - 将包名从
com.google.android.games.VkQualityTest
更改为与你的 Unity 项目设置 播放器类别中的 其他设置下的 包名称字段的值匹配(例如,com.mycompany.mygame
)。 - 保存并关闭该文件。
添加一个引用自定义活动的自定义清单文件,并告诉 Unity 使用您的自定义清单文件。
- 将插件包的
Assets/Plugins/Android
目录中的AndroidManifest.xml
文件复制到您项目的Asset/Plugins/Android
目录中。 - 在文本编辑器中打开该文件。
- 将
activity android:name
设置的值从com.google.android.games.VkQualityTest.VkQualityTestActivity
更改为在前面的步骤中使用的包和活动名称(例如,com.mycompany.mygame.MyGameActivity
)。 - 保存并关闭该文件。
- 打开 Unity 设置窗口,选择 Player 设置。展开 Publishing Settings 部分,选中 Custom Main Manifest 复选框。
您的项目现在已设置为使用自定义活动,该活动在启动时调用 VkQuality 并根据 VkQuality 建议选择 Vulkan 或 OpenGL ES。
将 VkQuality 添加到现有的自定义活动中
如果您的游戏已经有一个覆盖默认 UnityPlayerActivity
的自定义活动,请通过添加以下代码来集成 VkQuality 建议。
首先,将 VkQuality 导入语句添加到自定义活动文件顶部的导入列表中。
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; }
您的自定义活动现在在启动时调用 VkQuality 并根据 VkQuality 建议选择 Vulkan 或 OpenGL 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
枚举值。
要创建自定义建议列表文件,请使用位于 GitHub 存储库 中的 VkQuality 列表编辑器 工具。该工具的文档位于其 自述文件 中。