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

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

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

背景

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

一般的なテクスチャ圧縮形式には次の形式があります。

  • DDS または S3TC: DXTC または DXTn とも呼ばれます。この形式は 3 種類が OpenGL でサポートされています。
  • ETC1: ほとんどのデバイスでサポートされています。この形式は透明度をサポートしていませんが、2 つ目のテクスチャ ファイルをアルファ コンポーネント用に使用できます。
  • ETC2: GLES3 をサポートするデバイスのすべてでサポートされています。
  • PVRTC: iOS ゲームでは一般的な形式で、一部の Android デバイス上でもサポートされています。
  • ASTC: 以前のフォーマットを置き換える最新の形式です。さまざまなブロックサイズをサポートしているため、以前の形式よりも柔軟性が高くなっています。ゲームのサイズの最適化におすすめです。

以下に、形式ごとにそれをサポートしている Android デバイスの割合を示します。

テクスチャ圧縮形式 サポートしている Google Play デバイスの割合1
ETC1 99%
ETC2 87%
ASTC 77%
ATC 35%
PVRTC 11%
DXT1 0.7%

1 2020 年 9 月にアクティブな Google Play デバイスから収集したデータを使用して算出

デフォルトの形式

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

デフォルトの形式には、特定のデバイス ハードウェアをターゲットとする場合を除き、ほとんどのデバイスがサポートしている ETC1 と ETC2 が適しています。ゲームが OpenGL ES 3.0 以上をターゲットとする場合、確実に OpenGL ES 3.0 でサポートされる ETC2 形式のいずれかを選択するのであれば、ETC2 をデフォルトの形式として選択してもよいでしょう。

App Bundle をビルドする

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

Unity 以外のゲームの場合は、Gradle を使用して App Bundle をビルドします。上級者ならば bundletool を使用してもかまいません。

Unity のゲームの場合は、Unity プラグインを使用して App Bundle をビルドできます。

Gradle を使用する

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

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

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

  4. ゲームアセットを含み、Play Asset Delivery で使用されるアセットパックネイティブまたは 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. bundletool を GitHub リポジトリからダウンロードします。

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

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

  4. ゲームアセットを含み、Play Asset Delivery で使用されるアセットパックネイティブまたは 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 に設定します。これにより、ゲームはウェルノウンなディレクトリ名(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 の内容を確認する

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

出力された 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