VkQuality Unity引擎插件为特定设备上的游戏提供图形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引擎项目
插件包中Assets/Plugins/Android/VkQualityTestActivity.java
中包含一个使用VkQuality的自定义活动示例。插件包。要自定义文件并在游戏中使用它,请执行以下步骤
- 将
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 列表编辑器工具。该工具的文档位于其 README 中。