纹理是可应用于 3D 模型表面的图像。纹理还用于 2D 渲染器绘制诸如精灵或背景之类的元素。此页面描述了游戏中使用的流行纹理压缩格式以及如何在 Android 应用包中指定目标格式。在开始本指南之前,请阅读关于 Android 应用包和Play Asset Delivery。
背景
GPU 通常支持一组纹理压缩格式。纹理压缩格式 (TCF) 是一种针对 GPU 优化的文件格式。与使用内存中的 RGBA 值数组相比,GPU 加载和渲染纹理的速度更快,内存占用更少。此支持在硬件级别完成:GPU 制造商将读取、解压缩和渲染受支持格式的组件嵌入到显卡芯片中。
以下是现代移动硬件上的常见纹理压缩格式
- ASTC:最近设计的格式,旨在取代以前的格式。由于支持各种块大小,因此比以前的格式更灵活。使用此格式是优化游戏大小的一种好方法。
- ETC2:支持所有支持 OpenGL ES 3.0 及更高版本的设备。这包括几乎所有活跃的 Android 移动设备。
以下格式约占 Android 设备的百分比:
纹理压缩格式 | 支持 Google Play 设备的百分比 |
---|---|
ASTC | >80% |
ETC2 | >95% |
运行 Google Play 游戏 for PC 的桌面计算机 GPU 也支持此格式
- DDS 或 S3TC:有时称为 BCn、DXTC 或 DXTn。
较旧的、不再推荐的纹理压缩格式包括:
- ETC1:在大多数设备上受支持。此格式不支持透明度,但游戏可以使用第二个纹理文件作为 alpha 分量。
- PVRTC:iOS 游戏中很流行,也受一些 Android 设备支持。
ETC1 支持仅是支持非常旧的遗留设备或不支持 OpenGL ES 3.0 及更高版本的某些 Android TV 设备的游戏的要求。
默认格式
由于有如此多的可用格式(支持级别各不相同),因此在构建游戏纹理时可能不知道使用哪些格式。作为一项安全措施,应用包格式允许您为每个资源包选择默认的纹理压缩格式。如果设备不支持其他指定的格式,则会安装使用此默认格式的资源。
除非您要针对非常旧的设备硬件,否则 ETC2 是一个不错的默认格式选择。您应该使用保证在 OpenGL ES 3.0 中受支持 的 ETC2 格式。这些格式也可在 Vulkan 图形 API 中使用。
推荐格式
ASTC 格式定义了各种压缩块大小,允许您有选择地以降低图像质量为代价来获得更大的压缩率。根据源素材的性质,对于给定的纹理,您可以选择更小或更大的块大小以保持可接受的视觉质量。
如果您的游戏支持 Google Play 游戏 for PC 并使用 Vulkan,则应包含 S3TC 纹理。所有桌面 GPU 都支持 S3TC 格式。
构建应用包
Google Play 使用 Android 应用包为每个用户的设备配置生成和提供优化的 APK,因此用户只需下载运行游戏所需的代码和资源。这些优化的 APK 包括一组纹理资源,并使用适合设备的最佳压缩格式进行格式化。
如果您的游戏不在 Unity 中,请 使用 Gradle 构建应用包。高级用户可能希望 使用 bundletool
。
如果您的游戏在 Unity 中,则 Unity 2021.3 及更高版本支持使用 Play Asset Delivery 的应用包。更多信息,请参阅 Unity 文档。您可以 使用 Unity 插件 使用较低版本的 Unity 构建应用包。
使用 Gradle
将项目
build.gradle
文件中的 Android Gradle 插件版本更新到 4.1 或更高版本(例如,com.android.tools.build:gradle:4.1.0
)。确定您要为游戏定位的设备类型集以及它们支持的纹理压缩格式(有关格式的更多信息,请参阅 背景)。
为上一步中的每种纹理压缩格式构建资源版本。这可能涉及使用 TexturePacker 等软件生成精灵表,或运行将原始资源转换为具有特定格式的资源的脚本(例如,astc-encoder)。
创建 资源包(请参阅 为 C++ 或 Java 构建),其中包含您的游戏资源,并由 Play Asset Delivery 使用。例如,您可以为每个关卡创建一个资源包,或为游戏的不同部分创建资源包。
在您的资源包内,为要支持的每种纹理压缩格式添加目录。将 支持的后缀 添加到与包含文件使用的纹理压缩格式相对应的纹理目录名称中。
创建一个名称中没有后缀的目录(例如,
common/src/main/assets/textures/
)。在此目录中,放置纹理资源的默认格式。此默认格式应受大多数设备支持(例如,ETC1 或 ETC2)。如果设备不支持其他指定的格式(例如,下表中的 PVRTC 和 ASTC),则 Google Play 商店会安装此目录。目录之前 目录之后 common
资源包
common/build.gradle
common/src/main/assets/textures/...common
资源包
common/build.gradle
common/src/main/assets/textures/...
common/src/main/assets/textures#tcf_astc/...
common/src/main/assets/textures#tcf_pvrtc/...level1
资源包
level1/build.gradle
level1/src/main/assets/textures/...level1
资源包
level1/build.gradle
level1/src/main/assets/textures/...
level1/src/main/assets/textures#tcf_astc/...
level1/src/main/assets/textures#tcf_pvrtc/...level2
资源包
level2/build.gradle
level2/src/main/assets/textures/...level2
资源包
level2/build.gradle
level2/src/main/assets/textures/...
level2/src/main/assets/textures#tcf_astc/...
level2/src/main/assets/textures#tcf_pvrtc/...更新应用程序的
build.gradle
文件以启用按纹理拆分资源包。// In the app build.gradle file: android { ... bundle { texture { enableSplit true } } }
在 Android Studio 中,选择构建 > 生成签名包/APK,或从命令行启动 Gradle 任务 以生成您的包。
使用 Google Play Unity 插件
获取 Play Asset Delivery 的 Unity 插件(或包) 以使用针对纹理的资源包创建应用包。
准备资源
要为构建应用包准备纹理资源,请执行以下操作
将场景和资源打包到多个 Unity 资源包 中。
确定您要为游戏定位的设备类型集以及它们支持的纹理压缩格式(有关格式的更多信息,请参阅 背景)。
修改游戏的构建脚本以多次生成资源包,每次生成一次用于要支持的每种纹理格式。请参阅以下示例脚本
using Google.Android.AppBundle.Editor; using UnityEditor; public class MyBundleBuilder { [MenuItem("Assets/Build AssetBundles TCF variants")] public static void BuildAssetBundles() { // Describe the AssetBundles to be built: var assetBundlesToBuild = new [] { new AssetBundleBuild { assetBundleName = "level1-textures", assetNames = new[] {"level1/character-textures", "level1/background-textures"} }, new AssetBundleBuild { assetBundleName = "level2-textures", assetNames = new[] {"level2/character-textures", "level2/background-textures"} } }; // Describe where to output the asset bundles and in which formats: var outputPath = "Assets/AssetBundles"; var defaultTextureFormat = MobileTextureSubtarget.ETC2; var additionalTextureFormats = new[] { MobileTextureSubtarget.ASTC, MobileTextureSubtarget.PVRTC } var allowClearDirectory = true; // Generate asset bundles: AssetBundleBuilder.BuildAssetBundles( outputPath, assetBundlesToBuild, BuildAssetBundleOptions.UncompressedAssetBundle, defaultTextureFormat, additionalTextureFormats, allowClearDirectory); // While in this example we're using the UI to configure the // AssetBundles, you can use the value returned by BuildAssetBundles // to configure the asset packs, if you want to build the bundle // entirely using the scripting API. } }
验证每个纹理资源是否输出到名称中包含正确后缀的目录中(例如,
#tcf_astc
)。验证是否输出了一个名称中没有后缀的目录(例如,
Assets/AssetBundles/
)。此目录包含纹理资源的默认格式。此默认格式应受大多数设备支持(例如,ETC2)。如果设备不支持其他指定的格式(例如,上一步代码中的 ASTC),则 Google Play 商店会安装此目录。Assets/AssetBundles.meta Assets/AssetBundles/AssetBundles Assets/AssetBundles/AssetBundles.manifest Assets/AssetBundles/AssetBundles.manifest.meta Assets/AssetBundles/AssetBundles.meta Assets/AssetBundles/samplescene Assets/AssetBundles/samplescene.manifest Assets/AssetBundles/samplescene.manifest.meta Assets/AssetBundles/samplescene.meta Assets/AssetBundles/texturesbundle Assets/AssetBundles/texturesbundle.manifest Assets/AssetBundles/texturesbundle.manifest.meta Assets/AssetBundles/texturesbundle.meta Assets/AssetBundles#tcf_astc.meta Assets/AssetBundles#tcf_astc/AssetBundles Assets/AssetBundles#tcf_astc/AssetBundles.manifest Assets/AssetBundles#tcf_astc/AssetBundles.manifest.meta Assets/AssetBundles#tcf_astc/AssetBundles.meta Assets/AssetBundles#tcf_astc/samplescene Assets/AssetBundles#tcf_astc/samplescene.manifest Assets/AssetBundles#tcf_astc/samplescene.manifest.meta Assets/AssetBundles#tcf_astc/samplescene.meta Assets/AssetBundles#tcf_astc/texturesbundle Assets/AssetBundles#tcf_astc/texturesbundle.manifest Assets/AssetBundles#tcf_astc/texturesbundle.manifest.meta Assets/AssetBundles#tcf_astc/texturesbundle.meta
选择Google > Android > 资源交付。
单击添加文件夹以添加包含默认资源包的文件夹。这些包将安装在不支持您定义的其他格式的设备上。
确保为资源包设置交付模式。
单击添加文件夹以添加包含为另一种格式(例如,ASTC)构建的资源包的文件夹。根据需要重复此操作。
确保为每个资源包设置交付模式。
构建
选择Google > 构建 Android 应用包以启动游戏的 Unity 构建。它还会将资源包打包到多个资源包中,其中每个资源包名称都转换为单个资源包。
(高级)使用 bundletool
有关 bundletool
的更多信息,请参阅 使用 bundletool 构建应用包。
要创建应用包,请执行以下操作
从其 GitHub 存储库下载
bundletool
。确定您要为游戏定位的设备类型集以及它们支持的纹理压缩格式(有关格式的更多信息,请参阅 背景)。
为上一步中的每种纹理压缩格式构建资源版本。这可能涉及使用 TexturePacker 等软件生成精灵表,或运行将原始资源转换为具有特定格式的资源的脚本(例如,astc-encoder)。
创建 资源包(请参阅 为 C++ 或 Java 构建),其中包含您的游戏资源,并由 Play Asset Delivery 使用。例如,您可以为每个关卡创建一个资源包,或为游戏的不同部分创建资源包。
在不同的资源包中,将 支持的后缀 添加到与包含文件使用的纹理压缩格式相对应的纹理目录名称中。
创建一个名称中没有后缀的目录(例如,
common/src/main/assets/textures/
)。在此目录中,放置纹理资源的默认格式。此默认格式应受大多数设备支持(例如,ETC1 或 ETC2)。如果设备不支持其他指定的格式(例如,下表中的 PVRTC 和 ASTC),则 Google Play 商店会安装此目录。目录之前 目录之后 common
资源包
common/build.gradle
common/src/main/assets/textures/...common
资源包
common/build.gradle
common/src/main/assets/textures/...
common/src/main/assets/textures#tcf_astc/...
common/src/main/assets/textures#tcf_pvrtc/...level1
资源包
level1/build.gradle
level1/src/main/assets/textures/...level1
资源包
level1/build.gradle
level1/src/main/assets/textures/...
level1/src/main/assets/textures#tcf_astc/...
level1/src/main/assets/textures#tcf_pvrtc/...level2
资源包
level2/build.gradle
level2/src/main/assets/textures/...level2
资源包
level2/build.gradle
level2/src/main/assets/textures/...
level2/src/main/assets/textures#tcf_astc/...
level2/src/main/assets/textures#tcf_pvrtc/...将 TCF 维度添加到 应用包元数据文件(
BundleConfig.json
)中。使用TEXTURE_COMPRESSION_FORMAT
作为value
字段。{ ... "optimizations": { "splitsConfig": { "splitDimension": [ ... { "value": "TEXTURE_COMPRESSION_FORMAT", "negate": false, "suffixStripping": { "enabled": true, "defaultSuffix": "" } }], } } }
将
suffixStripping.enabled
设置为true
以在生成资源包时从目录名称中删除后缀(例如,#tcf_astc
)。这使您的游戏能够从众所周知的目录名称(例如,level1/assets/textures
)中读取文件。一些游戏引擎可以检测文件的格式,因此您的游戏可以不关心安装了哪种格式的纹理资源。suffixStripping.defaultSuffix
在bundletool
为运行 Android 5.0(API 级别 21)及更低版本的设备生成独立 APK 时指定默认目录后缀。在上表的示例中,纹理资源的默认版本将安装在这些设备上;这在大多数情况下是预期的行为。构建应用包
bundletool build-bundle --config=BUILD_CONFIG.json \ --modules=level1.zip,level2.zip,common.zip,base.zip --output=MY_BUNDLE.aab
验证应用包的内容
如果您尚未下载,请从 GitHub 存储库 下载 bundletool
。
通过从应用包构建 APK 并检查它们来验证输出应用包的内容
bundletool build-apks --output=APKS.apks --bundle=MY_BUNDLE.aab
zipinfo APKS.apks
输出应类似于以下内容
toc.pb
splits/base-master.apk
splits/base-armeabi_v7a.apk
splits/…
asset-slices/level1-astc.apk
asset-slices/level1-other_tcf.apk
asset-slices/level1-pvrtc.apk
这些名称表示已正确应用 TCF 定位。如果您提取关卡 APK(例如,asset-slices/level1-astc.apk
)的内容,则可以验证名为 textures
的目录只有一个。
测试应用包
连接设备并安装适用的资源包
bundletool install-apks --apks=APKS.apks
此命令仅安装满足设备规格的资源包。这些规格包括 ABI、屏幕密度、语言和最适用的纹理压缩格式。此操作模拟了 Google Play 商店为您发布的游戏执行的操作。
要验证是否安装了正确的资源包,请执行以下任一操作
使用
bundletool extract-apks
命令将设备上安装的apk输出到一个目录中,然后检查此目录。提取设备的规格
bundletool get-device-spec --output=MY_DEVICE_SPEC.json
使用此设备规格运行
bundletool extract-apks
bundletool extract-apks --apks=APKS.apks --device-spec=MY_DEVICE_SPEC.json \ --output-dir out
列出
out
目录中的文件,并验证是否安装了正确的资源包。资源包名称以纹理格式名称作为后缀(例如,level1-astc.apk
)。
在游戏中添加日志语句,在加载纹理时输出纹理格式。
生成一组测试纹理(例如,用给定格式的单一亮色替换纹理)。运行游戏并验证其是否存在。
如果您的应用包含on-demand
或fast-follow
资源包,请使用资源交付的本地测试解决方案。
纹理目录名称支持的后缀
Google Play 识别纹理目录名称中使用的以下后缀
#tcf_astc
用于自适应可缩放纹理压缩 (ASTC)#tcf_atc
用于 ATI 纹理压缩 (ATC)#tcf_dxt1
用于 S3 DXT1 纹理压缩 (DXT1)#tcf_latc
用于亮度-Alpha 纹理压缩 (LATC)#tcf_paletted
用于通用调色板纹理压缩#tcf_pvrtc
用于 PowerVR 纹理压缩 (PVRTC)#tcf_etc1
用于 Ericsson 纹理压缩 (ETC1)#tcf_etc2
用于 Ericsson 纹理压缩 2 (ETC2)#tcf_s3tc
用于 S3 纹理压缩 (S3TC)#tcf_3dc
用于 ATI 3Dc 纹理压缩 (3Dc)
Google Play 服务规则
Google Play 检查设备使用的 OpenGL 扩展字符串以及设备支持的 OpenGL 版本。Google Play 使用此信息来确定从 Android App Bundle 向设备交付正确的纹理格式。
Google Play 会交付设备支持的第一个格式,顺序如下表所示。
如果 App Bundle 中的任何纹理格式都不受设备支持,Google Play 会交付打包在默认格式中的纹理格式。(除非您针对特定设备硬件,否则 ETC1 或 ETC2 是默认格式的不错选择。)有关如何在默认格式中打包资源的信息,请参阅使用 bundletool或使用 Google Play Unity 插件。
如果资源未以默认格式打包,Google Play 会将应用标记为该设备不可用。在这种情况下,用户无法下载应用。
格式(在tcf_xxxx 中指定) |
在具有 OpenGL 扩展字符串的设备上受支持 |
---|---|
astc | GL_KHR_texture_compression_astc_ldr |
pvrtc | GL_IMG_texture_compression_pvrtc |
s3tc | GL_EXT_texture_compression_s3tc |
dxt1 | GL_EXT_texture_compression_dxt1 |
latc | GL_EXT_texture_compression_latc |
atc | GL_AMD_compressed_ATC_texture |
3dc | GL_AMD_compressed_3DC_texture |
etc2 | 不适用。设备必须支持 OpenGL ES 3.0 或更高版本。 |
etc1 | GL_OES_compressed_ETC1_RGB8_texture |
paletted | GL_OES_compressed_paletted_texture |