モバイルプラットフォームにおけるテクスチャ圧縮フォーマットの選択

今日の主な話題：

1）モバイルプラットフォームにおけるテクスチャ圧縮フォーマットの選択
2）Unity2018はMaliGPUでAlpha8形式をサポートしていますか？
3）Unityに付属するNavmeshで地面の高さを取得する方法
4）ParticleSystemは再生できません
5）UI開発において、インターフェースの開始順序に従って上部パネルに戻る問題

---
##Texture##

**Q： この前、テクスチャ圧縮に関する知識とUWAのいくつかのおすすめ方法について学びました。しかし、まだ少し疑問が残っているので、答えられることを期待して、ここでもう一度取り上げます。**

**テクスチャ圧縮フォーマットの選択では、2の2乗（ETC1とPVRTC）、縦横が等しい（PVRTC）という条件があるため、AndroidがETC、iOSがPVRTCを選択します。**

**問題1：アーティストのエクスポート図について、皆さんはどんなサイズを要求しますか？
エクスポート図なら、2の2乗にエクスポートします。
エクスポート図は2の2乗ではなく、UnityのディフォルトNPOTというオプションで自動的に変換させます。
他の方法？**

**問題2：上記1と2二つの方法は本質的な違いがありますか？UWAのXinさんが直接的にNPOTを使用する方法を主張しました（3年前の問題です）：**

A：まず問題4について答えましょう、この問題はその前の問題に影響を及ぼします。

2019年には、中国本土製品のiOSでのASTCはすでに問題はないと思います。 iPhone 5s及びその以前のデバイスは駄目です。メモリはゲームに十分です（もちろん、ゲームの種類によって異なります。カジュアルゲームの場合は互換性を高めることを検討する必要があります）。もう1つはiPad miniと古いiPadは駄目です。iPadの更新頻度は比較的低いため、古いデバイスが多いです。ただ、全体的な市場シェアも低いです。

AndroidならETC2で十分だと思います、normalなどのような特殊的なスタンプは特別な圧縮方法を使用します、強制的にASTCを使用する必要がありません。

iOS：2018年に開始されたプロジェクトは強いてASTCを使用しました。これは主にUIがPVRTCの圧縮効果を受け入れないからです。

このような状況には：
問題1：四角形なら考慮する必要はありません。重要ではありません。 POTに準拠することをお勧めします。これは、GPUのパフォーマンスに優れており、合成とアート仕様で処理できます。

問題2：ほとんどの場合、本質的な違いはなく、スタンプはUVに沿ってサンプリングすれば問題ありません。個人的には、POTを基本的なアート仕様にする傾向があります（特別なLoading図などを除きます）。もうひとつは、アーティストは、より大きなサイズで同じようなコストが必要な場合、ディテールを加えることができるかもしれません。

問題3：効果が歪んでいない場合はRGBA16を検討できます。300 * 300に関しては、256 * 256にすることを選択できますが、全体としては圧縮的なフォーマットをお勧めします。これは、ほとんどの場合（メモリ使用量+全体的な効果の考慮）RGBA16よりも優れています。

一般的に、UIはほとんどのPOTや3Dに合成するものを、POTのフォーマットで設計や製作します。これなら、全体的な仕様を簡単に作成できます。特殊的な部分はNPOTを使用します。比較的小さな部分にのみ影響します。

---
##Texture##


Q：テストデバイス型番OPPO A3、スタンプサイズ1024*1024

**テストサンプル一：
Unity 2017.4.16 / Alpha 8写真21枚**

**テスト結果：**

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/ff24c725-599b-becc-c8fe-94a12473f217.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/2bb23955-b0b8-85fe-d2d4-78cef1a1bd0d.png)
**テストサンプル二：
Unity 2018.3.13 / Alpha 8写真11枚/ R8写真11枚**

**テスト结果：**
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/bc1a65c0-ac35-c811-859b-af83c9743e24.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/b27bab71-8eb3-77b0-d991-333a11185980.png)
**第一枚の写真の対照から、Unity 2017.4.16はAlpha 8フォーマットをサポートしませんが、Unity 2018.3.13のフォーマットはAlpha 8フォーマットスタンプをサポートします。第二枚の写真において、Graphicsメモリのサイズの検証からUnity 2017のAlpha 8フォーマットは4MBのRGBA32までFallBackしますが、Unity 2018のAlpha 8フォーマットのメモリは1MBのままで保持します。**

**同時には、SnapDragon Profilerを用いて、XIAOMI 5デバイスでフレームをキャプチャーしたところ、Unity 2018にパッケージ化されたAPKには、Alpha 8フォーマットがR8フォーマットに変換されたことに気づいました。**

**簡単に言えば：Unity 2017.4.16でパッケージ化されたAPKは、Alpha 8をサポートしません。その上に、RGBA32フォーマットにFallbackされました。それに対して、Unity 2018.3.13でパッケージ化されたAPKは、Alpha 8をサポートします。それに、SnapDragon Profilerを用いてフレームをキャプチャーするところ、GPUにおいてR8のフォーマットとして存在しています。**

**問題一：Unity 2018.3.13はAlpha 8フォーマットのスタンプをサポートできますか？
問題二：Unity 2018のR8フォーマットはIosまたはAndroidにおいて、ハードウェアに対して何か要求がありますか？**
A：問題1：

GLES3 の場合、UnityはシングルチャンネルAlpha 8の図をR8にします。これは問題主のスクリーンショットはR8の図である原因です。Shaderにおいて、Alphaチャンネルを使用してR8スタンプにあるRチャンネルのデータを取得するため、Texture Swizzleというメカニズムを依存する必要があります。Unity 2018の場合、残念ながら、GPUがMaliで、システムバージョンがMarshmallow以上のデバイスでは、TextureSwizzleメカニズムに問題があると判断されます。したがって、UnityはAlpha 8をRGBAフォーマットに直接フォールバックします。これにより、GPUの対応するテクスチャメモリが4倍になります。

問題2：

1）GLES 2.0の場合、UnityはAlpha 8イメージを直接サポートしているため、R8への転送の問題を考慮する必要はありません。もちろん、R8自体もサポートされています。
2）iOSの場合、まだテストしていないので、結論を出すことはできません。

---


##Navmesh##

Q：キャラクターが動くとき、重力や剛体を使用しません。プレイヤーがポイントに移動したい場合、y座標は地形の高さを取得する必要があります。これを行うための良い方法はありますか？

A：地形データをバイナリとして保存すると、xとyに基づいて高さを取得できます。 歩くことができるかどうかを記録し、全体を大きな2次元配列に記録してから、ローカルファイルに直接保存することができます。 読み取るときは、xとzに従って2次元配列の対応するマップデータに直接インデックスを付けます。

---


##ParticleSystem##

Q：特殊効果の表示と非表示を設定する場合、SetActive true / falseを使用する代わりに、画面の外に移動してから、animator enable true/falseで、Animator instanceのコストを削減できます。

そのとき、特殊効果に付いているパーティクルは再生できず、特殊効果が画面の外側から内側に移動すると、特殊効果のパーティクルが失われます。[コードと特殊効果を添付してください](https://answer.uwa4d.com/question/5de0947e30e0542f29cd5c6a)

```
{
        if (obj == null)
            return;

//         //表示と非表示を設定するには、一時的にパーティクルシステムを再生できないという問題が発生する時、元の方法を使用してください
//        obj.SetActive(bActive);
//        return;

        Vector3 pos = obj.transform.localPosition;
        Animator[] Anis = obj.GetComponentsInChildren<Animator>();

        //animatorない 現像に直接SetActive true/fasle
        if(Anis.Length <= 0)
        {
            obj.SetActive(bActive);
            return;
        }
        if (bActive)
        {
            if (pos.x > 10000)
            {
                pos.x = pos.x - 10000;
            }
        }
        else
        {
            if (pos.x < 10000)
            {
                pos.x = pos.x + 10000;
            }
        }
        for (int i = 0, count = Anis.Length; i < count; i++)
        {
            Anis[i].enabled = bActive;
            if (bActive)
            {
                AnimatorStateInfo anif = Anis[i].GetCurrentAnimatorStateInfo(0);
                Anis[i].Play(anif.nameHash, 0, 0);
            }
        }
       // if(bActive)
        {
            ParticleSystem[] pars = obj.GetComponentsInChildren<ParticleSystem>();
            for(int i = 0, count = pars.Length; i<count;i++)
            {
                if (bActive)
                    pars[i].Play();
                else
                    pars[i].Pause();
            }
        }
        obj.transform.localPosition = pos;
    }
```
A：次の書き込み方法は、当分の間、まだ問題主が言った状況が現れません：

```
// 再生を開始する
foreach (var particleSystem in m_ParticleSystems)
{
    particleSystem.time = 0;
    particleSystem.Play(false);  // false参数不递归子物体
}

//再生を終了する
foreach (var particleSystem in m_ParticleSystems)
{
    particleSystem.Clear(false);
    particleSystem.Stop(false);
}
```

---
##UI##

Q：UI開発では、インターフェイスの戻る方法として、スタックで実現させます。パネル情報をスタックに保存しますが、新しく開けたいパネルがすでにスタックに存在していることが現れます。こういう場合、どのように対処しますか。また、リングで出現するかもしれません。例えば、A→B→C→A→B→Cのようなリングにどう対処しますか。またリングであるかどうかをどのように判断しますか？設計では避けますが、現れた場合、どうすればよいでしょうか。皆さんに助けをお願いします。**
A1：完備なデータとパフォーマンスの分離をした場合、現在インターフェースのステート：例えば選択したTabページ、スクロール位置などの情報を保存します。スタックに保存されたインターフェースIDとこれらの情報は、すでに存在したスタックを完全にサポートできます。

もちろん、プランナーと確認してもいいです。上記のような新しいパネルはスタックに存在する対処法として：スタックから削除して新しい位置に追加したらどうでしょうか。ロジック的にはいいけれども、パフォーマンスは適切かどうかを確認する必要があります。

最後に、スタックが記録しているのは、プレイヤーがこの前に見たインターフェースであるため、リングがあったとしても、無限なリングではありません。さらに、このスタックには通常的には上限があるはずです。あるクリアのタイミングに合わせて、メモリ使用量が多すぎるの問題を避けれます。

A2：一般的なインターフェースは第1レベルのパネル、第2レベルのパネル、第3レベルのパネル、第4レベルのパネル、Tipsパネルなど、階層的に設計されています。同じレベルには、同時に1つのパネルを開くか、左と右の各側に1つを開くことができます。

上位パネルから下位パネルにスキップすると、下位レベルより上のスタックデータが直接クリアされます。例：Aは第1レベルのパネル、Bは第2レベルのパネル、Cは第3レベルのパネルです。 CからAへとスキップした時に、第2と3レベルのデータが直接クリアされ、第1番目のレベルのパネルのデータが置き換えられます。

確認したい場合は、下から直接スキャンし、同じものが見つかったら、この位置以上のものをクリアします。次に例を示します。A–> B–> Cこの時点で、Aを開き、Aがすでに0番目の位置に存在することを確認し、位置1より上のノードを直接削除します。

スタックは使用しないでください。配列を直接使用する方が便利です。

---
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、パフォーマンス分析と最適化ソリューション及びコンサルティングサービスを提供している会社でございます。

UWA公式サイト：https://jp.uwa4d.com
UWA公式ブログ：https://blog.jp.uwa4d.com