パッケージサイズを最適化する方法

今回の主な話題：パッケージサイズを最適化する方法、パッケージ化に付属のUnityAdsファイルを削除する方法、不透明なオブジェクトのレンダリング順序、Shadows.CullDirectionaShadowCastersのコスト分析、PC版のモニター解像度の取得方法。

---
###アセット管理
Q1: 現在、プロジェクトの初期段階で出力されたAPKは数GBであり、廃棄されたリソースの一部はまだ整理されていないことがわかっています。一般的に、皆さんはパッケージサイズの最適化に何をしていますか？一部のゲームは、小さいパッケージ＋リソースパッケージをダウンロードすることでやります。これも予備案にします。単純にパッケージ本体を最適化する体系的な経験はありますか？ これには、リソース関連のものやその他のものを含めることができます。

①
>
最近、私もパッケージの問題を処理しています。自分経験について話します。
>
1）皆さんがよく言っている冗長リソースを削除すること＋リソース形式を設定することはもう説明しません。フォーラムにこれについて記事も多いし、この部分が最も大きな影響を与えます。
>
2）アトラスを合理的に計画し、空白をできるだけ少なくします。移動してサイズを一つのレベルに縮小できます。TexturePackerを使用してパッケージ化するチームは、急進的に特別シーンで回転とTrimmingを使用して、アトラスをパッケージ化できます。
>
3）UIサイズを合理的に対処します。一般的にUIがMipmapを開かないために、UIサイズを自分でコントロールするほうがいいです。大きな背景画像やアイコンに対して、9マスまたは対称を使用して、残りの部分を生成します。
>
4）ABIは、プロジェクトの要件に応じてX86アーキテクチャを削除できます。IL2CPPプロジェクトの削減は明らかです（通常、一つのIL2CPPコードの同じサイズに削減します）。そして、インポートされたプラグインを含むプロジェクト内のC＃コードの総量を合理的にコントロールすることで、生成されるIL2CPPコードのサイズを効果的に削減できます。
>
5）視野角が固定されている場合は、3DモデルテクスチャのMipmapを直接閉じて、適切なテクスチャサイズを直接選択すればいいです。 アートに関しても、モデルのサイズを縮小するために、目に見えない部分を削除することもできます。
>
実際、プロジェクトのすべての部分が多かれ少なかれパッケージ本体に影響を与え、詳しく話したい場合、1日も足りません。計画フォームもパッケージ本体にも影響するため、80/20の原則に従って最も影響力のある部分を見つけて解決し、効果が最も明白になるようにすることをお勧めします。

②
>
単純なパッケージの最適化には、次の3つの基本ポイントを実行する必要があると思います。
>
1）すべての冗長なリソースを排除します。
2）適切なリソース圧縮形式を設定します。
3）リソース（UIの9マステクスチャなど）を合理的に生成します。
>
以上に関しては、UWA公式ブログ（https://blog.jp.uwa4d.com) で多くの記事を検索できるので、ここでは説明しません。
>
基本パッケージ+リソースパッケージを動的にダウンロードすることは、基本的に、プレーヤーができるだけ早くゲームに参加できるようにするためのものです。

③
>
すべてのAssetBundleパッケージを圧縮し、UWAのリソース検出と分析ツールを使用して、冗長ファイル/非圧縮ファイルが多いかどうかを確認できます。

④
>
リソースの冗長性を検査すること以外に、Android App Bundleを試すこともできます。
https://developer.android.com/platform/technology/app-bundle を参考してください。
Unity2017.4.17f1ではもうサポートされています。

---
###構築
Q2: 図に示すように、BuildReportにはportrait.jpgとlandscape.jpgの2つのファイルがあり、UnityAdsによって提供されているようですが、UnityAdsを使用していません。また、これら2つの画像がどこにあるかを見つけることもできないし、ファイルも非常に大きいです。これら2つのファイルを削除する方法を知っている人はいますか。 どうもありがとう。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/a5ad52ed-abc2-91a8-874a-492e7c6db782.png)

>UnityインストールディレクトリDataResourcesPackageManagerEditormanifest.jsonを見つけ、manifest.jsonファイルのdependenciesをクリアし、安全のためにフォルダー内のいくつかの圧縮ファイルも削除します。これにより、Unity 2017.4.1バージョンでリソースのインポート時にportrait.jpgおよびlandscape.jpgでスタックする問題も解決できます。

---
###レンダリング
Q3: 不透明オブジェクトがレンダリングされた時には、一体どのように並べ替えられますか。時々に、正確な順序に付けられていない場合があるのはなぜですか。いつも前から後ろの順番だと思っていましたが、今日よく見てみると、そうではないようです。原因はわかりません。

以下は、テストシーンのスクリーンショットです。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/f6b42697-4ef1-26b8-4015-e6338955fa49.png)
シーンには3つのCubeがあります（赤色には拡大縮小があります）。nameは右から左に1、3、2です。カメラは右端にあります。2つの緑色のオブジェクトは同じマテリアルですが、赤色のオブジェクトは別のマテリアルです。２つのShaderは色のみが違って、他には完全に同じで、ShaderはStandardです。現在、赤いオブジェクトが右に配置されると、レンダリングは前から後ろの順序で完全にレンダリングされます（つまり、1-3-2）。

そして、赤いオブジェクトの位置を左に少し調整しました。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/8d690fa6-0bb6-969a-4f74-6606148b7dc1.png)
まだ2つの緑のCubeの間にあり、レンダリング順序は1-2-3になります（つまり、前のCubeが最初にレンダリングされ、最後のCubeがレンダリングされ、真ん中の赤いCubeが最後にレンダリングされます）。前後の順序に従わなくなります。

さらに奇妙なのは、この位置関係の下で、赤いCubeのマテリアルを緑の立方体と同じに変更すると、レンダリング順序が前から後ろに再びプログラムされることです。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/5861cfe1-c909-accc-238f-dde00870985f.png)
よくわからないので、聞きたいです。

①
>
原則はいくつあります。
>
1）自分で決めた場合には、自分で決めることができます。（Camera Depth、Render Queueなど）
2）まずは結果が正しいことを確認します。
3）次にパフォーマンスが可能な限り良好であることを確認します。
>
不透明なオブジェクトに対して、z testがあるため、任意の順序でレンダリングでき、結果は常に正しいので、主に3次第です。主要な原因は２つあります。
>
1）（ハードウェア）early-zに適しています。互いに遮られているオブジェクトに対して、通常、最初にカメラに近いオブジェクトを描画し、次にカメラから遠いオブジェクトを描画します。これにより、early-z時に後にレンダリングされたオブジェクトを直接Cullingできます（最初にレンダリングされたオブジェクトに遮られました）。お互いに遮られないものにはどうしてもいいです。これもGPUにも関連しています。TBDRのpowerVRなどのより高級なハードウェアCullingがある場合、自分で並べ替えを行う必要はありません。ハードウェアは自動的に処理（HSR）して完璧なCullingを行います。
>
2）レンダリング状態の切り替えを可能な限り減らします。ABCDがあり、AとDのレンダリング状態（Mesh、Shader、Texture、Uniform、Blend Settingなど）、BとCのレンダリング状態は同じように仮定したら、ADBCはよりいいで、レンダリング状態が1回だけ切り替えられる（AD→BC）、そうでない場合は2回（A→BC→D）です。レンダリング状態の切り替えコストも異なるため、通常はFBO、Shader、Texture、Uniform降順で配置されます。
>
1と2が衝突する場合は、Unityがどちらのソートパフォーマンスが優れているかを評価する方法によって異なります。

②
>
不透明なレンダリングの並べ替えは、距離に基づで前から後までだけでなく、多くのことに関連しています。大きなレイヤーは、Camera的Depth、Sorting Layers、SortingOrder、RenderQueueです。
>
レンダリング順序に影響を与える多くの方面があります。たとえば、最初のPassが最初にレンダリングされ、ベイク処理の場合はLightMapIndexも影響します。もう一つのはMaterialが同じかどうかです。Materialが同じである場合、Passも影響されます。パッチ処理がオンにすると、パッチにも影響があります。

---
###レンダリング
Q4: QualitySettingがShadow TypeもNo Shadowに変更した後、なぜShadows.CullDirectionalShadowCastersにまだコストがありますか？

>一般的には、Shadows.CullDirectionalShadowCastersコストはないはずです。UnityのBugの疑いがあります。
>
解決策は次のとおりです。QualitySettingのShadow TypeをNo Shadowに変更したら、シーンにあるDirectional lightのShadow typeをNo Shadowに設定します。Profilerを観察し、確かに消えました。Unityバージョンは2017.4.15f1であります。

---
###画像解像度
Q5: PC版はどのようにしてモニターの解像度を取得しますか？ 私はPCバージョンを以下のように望んでいます：

1）初期解像度はモニターの解像度を超えてはなりません。
2）プレーヤーが境界線をドラッグでき、ウィンドウの比率を確認できるようにサポートします。

できるかどうかがわからないこと：起動時にモニターの解像度に従って強制的に設定し、解像度変更イベントを監視して、毎回16：9に設定します。

>可能です。
>
1）ゲームの初期化スクリプトで、Screen.SetResolutionをコールして目標解像度を設定します。
2）WM_DISPLAYCHANGEを使用して解像度変更メッセージを監視し、Screen.SetResolutionを再度コールします。
>
Windowsイベントを監視することはめんどくさいと心配する場合は、優雅ではない方法があります。一つのタイマーを使用して、画面の解像度が変更されたかどうかを検出できます。ここでは、自分でWndProcを実現する必要があります。以下を参考できます。
>
http://www.waffle-maker.sakura.ne.jp/wordpress/?p=122

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

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