纹理是图像,可以应用于 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 是一个很好的默认格式选择。您应该使用 ETC2 格式,这些格式保证在 OpenGL ES 3.0 中受支持。这些格式在 Vulkan 图形 API 中也可用。
推荐格式
ASTC 格式定义了各种压缩块大小,允许您在降低图像质量与获得更高压缩率之间进行选择。根据源艺术素材的性质,您可以为给定纹理选择较小或较大的块大小,以保持可接受的视觉质量。
如果您的游戏支持 Google Play Games for PC 并且使用 Vulkan,则应包含 S3TC 纹理。S3TC 格式受所有桌面 GPU 支持。
构建应用包
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 AssetBundles 中。
确定要针对的游戏设备类型集以及它们支持的纹理压缩格式(有关格式的更多信息,请参阅 背景)。
修改游戏的构建脚本,以便为每个要支持的纹理格式多次生成 AssetBundles。请参阅以下示例脚本
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 > 资产传递。
单击添加文件夹以添加包含默认资产包的文件夹。这些包安装在不支持您定义的其他格式的设备上。
确保为 AssetBundle 设置传递模式。
单击添加文件夹以添加包含为另一种格式构建的 AssetBundles 的文件夹(例如,ASTC)。根据需要重复此操作。
确保为每个 AssetBundle 设置传递模式。
构建
选择Google > 构建 Android 应用包以启动游戏的 Unity 构建。它还会将 AssetBundles 打包到多个资产包中,其中每个 AssetBundle 名称都转换为单个资产包。
(高级)使用 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
命令将为您的设备安装的 apks 输出到目录中,然后检查此目录。提取设备的规范
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
用于爱立信纹理压缩 (ETC1)#tcf_etc2
用于爱立信纹理压缩 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 |
调色板 | GL_OES_compressed_paletted_texture |