Android App Bundle のテクスチャ圧縮形式をターゲット設定する

テクスチャは、3D モデルの表面に適用できる画像です。テクスチャは、2D レンダラがスプライトや背景などの要素を描画する際にも使用されます。このページでは、ゲームで使用される一般的なテクスチャ圧縮形式と、それらを Android App Bundle でサポートする方法について説明します。このガイドを開始する前に、Android App Bundle についてPlay Asset Delivery をご覧ください。

背景

通常、GPU は一連のテクスチャ圧縮形式をサポートしています。テクスチャ圧縮形式(TCF)は、GPU に合わせて最適化されたファイル形式です。これを使用することにより、GPU は、メモリ内の RGBA 値の配列を使用するよりも、高速かつ少ないメモリでテクスチャを読み込み、レンダリングすることができるようになります。テキスチャ圧縮方式へのサポートはハードウェア レベルでなされます。GPU メーカーは、サポートしている形式の読み取り、圧縮解除、レンダリングを行うコンポーネントをグラフィック カードのチップに組み込んでいます。

最新のモバイル ハードウェアにおける一般的なテクスチャ圧縮形式は、次のとおりです。

  • ASTC: 以前の形式に優先する最新の形式です。さまざまなブロックサイズをサポートしているため、以前の形式よりも柔軟性が高くなっています。ゲームのサイズの最適化におすすめです。
  • ETC2: OpenGL ES 3.0 以上をサポートするすべてのデバイスでサポートされています。 アクティブなほぼすべての Android モバイル デバイスが対応しています。

上記の形式をサポートする Android デバイスのおおよその割合は次のとおりです。

テクスチャ圧縮形式 サポートしている Google Play デバイスの割合
ASTC 80% 以上
ETC2 95% 以上

PC 版 Google Play Games を搭載しているデスクトップ パソコンの GPU は、次の形式もサポートしています。

  • DDS または S3TC: BCn、DXTC、DXTn とも呼ばれます。

以下の古いテクスチャ圧縮形式は非推奨となりました。

  • ETC1: ほとんどのデバイスでサポートされています。この形式は透明度をサポートしていませんが、2 つ目のテクスチャ ファイルをアルファ コンポーネントに使用できます。
  • PVRTC: iOS ゲームでは一般的な形式で、一部の Android デバイスでもサポートされています。

ETC1 のサポートが要件となっているのは、非常に古い以前のデバイスや、OpenGL ES 3.0 以上をサポートしていない一部の Android TV デバイスに対応しているゲームのみです。

デフォルトの形式

利用可能な形式が非常に多い(デバイスのサポートレベルも異なる)ため、ゲーム テクスチャの作成時にどの形式を使用すればよいかわからない場合に備えて、App Bundle 形式では、アセットパックごとにデフォルトのテクスチャ圧縮形式を選択できます。指定された形式をデバイスがサポートしていない場合、このデフォルトの形式を使用するアセットがインストールされます。

非常に古いデバイス ハードウェアをターゲットとしている場合を除き、ETC2 をデフォルトの形式として選択することをおすすめします。OpenGL ES 3.0 でのサポートが保証されている ETC2 形式を使用してください。 ETC2 形式は Vulkan Graphics API でも使用できます。

ASTC 形式ではさまざまな圧縮ブロックサイズが定義されているため、画質を下げて圧縮率を上げることも選択できます。ソースのアート素材の性質に応じて、許容可能な範囲で画質を維持するよう、テクスチャごとに選択するブロックサイズを小さくしたり大きくしたりできます。

ゲームが PC 版 Google Play Games に対応し、Vulkan を使用する場合は、S3TC テクスチャを追加する必要があります。S3TC 形式は、すべてのデスクトップ GPU でサポートされています。

App Bundle をビルドする

Google Play は、App Bundle を使用して、各ユーザーのデバイス設定に合わせて最適化された APK を生成して配信します。これにより、ユーザーはゲームの実行に必要なコードとリソースのみをダウンロードします。最適化された APK には、デバイスに最適な圧縮形式でフォーマットされたテクスチャ アセットのセットが 1 つ含まれています。

Unity 以外のゲームの場合は、Gradle を使用して App Bundle をビルドします。上級レベルの場合は bundletool を使用することもできます。

Unity のゲームでは、Unity 2021.3 以上の App Bundle で Play Asset Delivery を利用できます。詳しくは、Unity のドキュメントをご覧ください。Unity のバージョンがそれより低い App Bundle は、Unity プラグインを使用してビルドできます。

Gradle を使用する

  1. プロジェクトの build.gradle ファイル内の Android Gradle プラグインのバージョンを 4.1 以上(com.android.tools.build:gradle:4.1.0 など)に更新します。

  2. ゲームのターゲットとするデバイスタイプと、そのデバイスタイプでサポートされているテクスチャ圧縮形式を確認します(形式の詳細については、背景をご覧ください)。

  3. 前のステップで確認したテクスチャ圧縮形式ごとに、アセットのバージョンを作成します。その過程で、TexturePacker などのソフトウェアを使用してスプライト シートを生成する場合や、未加工のアセットを特定の形式に変換するスクリプト(astc-encoder など)を実行する場合があります。

  4. ゲームアセットを含み、Play Asset Delivery で使用されるアセットパックを作成します(C++ または Java 向けのビルドをご覧ください)。たとえば、レベルごとに 1 つのアセットパックを作成したり、ゲームのパートごとにアセットパックを作成したりすることもできます。

  5. アセットパック内で、サポートするテクスチャ圧縮形式ごとにディレクトリを追加します。テクスチャ ディレクトリ名には、その中のファイルに使用されるテクスチャ圧縮形式に対応するサポートされている接尾辞を追加します。

    名前に接尾辞のないディレクトリを作成します(例: 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/...
  6. アプリの build.gradle ファイルを更新して、テクスチャごとにアセットパックを分割できるようにします。

    // In the app build.gradle file:
    android {
        ...
        bundle {
            texture {
                enableSplit true
            }
        }
    }
    
  7. Android Studio で [Build] > [Generate Signed Bundle / APK] を選択するか、コマンドラインから Gradle タスクを起動して、バンドルを生成します。

Google Play Unity プラグインを使用する

Play Asset Delivery 用の Unity プラグイン(またはパッケージ)を入手して、テクスチャをターゲット設定したアセットパックを含む App Bundle を作成します。

アセットを準備する

以下の手順で、App Bundle をビルドするためのテクスチャ アセットを準備します。

  1. シーンとアセットを複数の Unity AssetBundle にパッケージ化します。

  2. ゲームのターゲットとするデバイスタイプと、そのデバイスタイプでサポートされているテクスチャ圧縮形式を確認します(形式の詳細については、背景をご覧ください)。

  3. ゲームのビルド スクリプトを変更して、AssetBundle を複数回(サポートするテクスチャ形式ごとに 1 回)生成するようにします。次のサンプル スクリプトをご覧ください。

    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.
       }
    }
    
  4. 各テクスチャ アセットが、正しい接尾辞のある名前のディレクトリに出力されていることを確認します(#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
    
  5. [Google] > [Android] > [Assets Delivery] を選択します。

  6. [Add Folder] をクリックして、デフォルトのアセット バンドルが入っているフォルダを追加します。このバンドルは、定義した他の形式に対応していないデバイスにインストールされます。

    AssetBundle の [Delivery mode] が設定されていることを確認します。

    Unity AssetBundle の配信、デフォルトの形式

  7. [Add Folder] をクリックして、別の形式(たとえば ASTC)のために作成された AssetBundle が入っているフォルダを追加します。必要なだけ繰り返してください。

    各 AssetBundle の [Delivery mode] が設定されていることを確認します。

    Unity AssetBundle の配信、ASTC 形式

ビルド

[Google] > [Build Android App Bundle] を選択して、ゲームの Unity ビルドを開始します。また、これによって AssetBundle は複数のアセットパックにパッケージ化されます。このとき、各 AssetBundle 名が 1 つのアセットパックに変換されます。

(上級者向け)bundletool を使用する

bundletool の詳細については、bundletool を使用して App Bundle をビルドするをご覧ください。

App Bundle は次の手順で作成します。

  1. GitHub リポジトリから bundletool をダウンロードします。

  2. ゲームのターゲットとするデバイスタイプと、そのデバイスタイプでサポートされているテクスチャ圧縮形式を確認します(形式の詳細については、背景をご覧ください)。

  3. 前のステップで確認したテクスチャ圧縮形式ごとに、アセットのバージョンを作成します。その過程で、TexturePacker などのソフトウェアを使用してスプライト シートを生成する場合や、未加工のアセットを特定の形式に変換するスクリプト(astc-encoder など)を実行する場合があります。

  4. ゲームアセットを含み、Play Asset Delivery で使用されるアセットパックを作成します(C++ または Java 向けのビルドをご覧ください)。たとえば、レベルごとに 1 つのアセットパックを作成したり、ゲームのパートごとにアセットパックを作成したりすることもできます。

  5. 各アセットパックのテクスチャ ディレクトリ名に、ディレクトリ内のファイルで使用されるテクスチャ圧縮形式に対応する、サポートされている接尾辞を追加します。

    名前に接尾辞のないディレクトリを作成します(例: 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/...
  6. App Bundle メタデータ ファイルBundleConfig.json)に TCF ディメンションを追加します。次のように value フィールドに TEXTURE_COMPRESSION_FORMAT を使用します。

    {
      ...
      "optimizations": {
        "splitsConfig": {
          "splitDimension": [
          ...
          {
             "value": "TEXTURE_COMPRESSION_FORMAT",
             "negate": false,
             "suffixStripping": {
               "enabled": true,
               "defaultSuffix": ""
              }
          }],
        }
      }
    }
    

    アセットパックの生成時にディレクトリ名から接尾辞(#tcf_astc など)を削除するように、suffixStripping.enabledtrue に設定します。これにより、ゲームは well-known ディレクトリ名(level1/assets/textures など)からファイルを読み取ることができます。一部のゲームエンジンはファイルの形式を検出できるため、一緒にインストールされたテクスチャ アセットの形式に依存しないゲームにすることもできます。

    suffixStripping.defaultSuffix は、bundletool が Android 5.0(API レベル 21)以前を搭載したデバイス向けのスタンドアロン APK を生成する際のデフォルト ディレクトリ接尾辞を指定しています。上の表の例では、デフォルト バージョンのテクスチャ アセットがこれらのデバイスにインストールされます。ほとんどの場合、これが意図された動作です。

  7. App Bundle をビルドします。

    bundletool build-bundle --config=BUILD_CONFIG.json \
      --modules=level1.zip,level2.zip,common.zip,base.zip --output=MY_BUNDLE.aab
    

App Bundle の内容を確認する

まだダウンロードしていない場合は、GitHub リポジトリから bundletool をダウンロードしてください。

出力された App Bundle から APK をビルドして、その APK を検査することにより、App Bundle の内容を検証します。

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 という名前のディレクトリのみが存在することを確認できます。

App Bundle をテストする

デバイスを接続して、適切なアセットパックをインストールします。

bundletool install-apks --apks=APKS.apks

このコマンドにより、デバイスの仕様を満たすアセットパックのみがインストールされます。この仕様には、ABI、画面密度、言語、最も適切なテクスチャ圧縮形式などがあります。この操作により、公開されているゲームに対して Google Play ストアで何が行われるかがシミュレートされます。

正しいアセットパックがインストールされたことを確認するには、次のいずれかを行います。

  • bundletool extract-apks コマンドを使用して、デバイスにインストールされる APK をディレクトリに出力し、そのディレクトリを検査する。

    1. デバイスの仕様を抽出します。

      bundletool get-device-spec --output=MY_DEVICE_SPEC.json
      
    2. このデバイス仕様を指定して bundletool extract-apks を実行します。

      bundletool extract-apks --apks=APKS.apks --device-spec=MY_DEVICE_SPEC.json \
          --output-dir out
      
    3. out ディレクトリのファイルを一覧表示し、適切なアセットパックがインストールされていることを確認します。アセットパック名の接尾辞が、テクスチャ形式名(例: level1-astc.apk)になっています。

  • テクスチャを読み込むときにテクスチャ形式を出力するログ ステートメントをゲームに追加する。

  • テクスチャのテストセットを生成する(たとえば、指定した形式に対してテクスチャを 1 色の明るい色に置き換えるなど)。ゲームを実行して、テストセットが存在することを確認します。

アプリに on-demand アセットパックまたは fast-follow アセットパックが含まれている場合は、アセット配信のローカルテスト ソリューションを使用します。

サポートされているテクスチャ ディレクトリ名の接尾辞

Google Play は、テクスチャ ディレクトリ名で使用される接尾辞として、次のものを認識します。

  • #tcf_astc: Adaptive Scalable Texture Compression(ASTC)
  • #tcf_atc: ATI テクスチャ圧縮(ATC)
  • #tcf_dxt1: S3 DXT1 テクスチャ圧縮(DXT1)
  • #tcf_latc: Luminance-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 の中のどのテクスチャ形式もデバイスでサポートされていない場合は、デフォルトの形式でパッケージ化されたテクスチャ形式を配信します(特定のデバイス ハードウェアをターゲットにしていない限り、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