oc

Unity Performance Best Practices 日本語訳

この記事はスマフォスロットイン系HMD Advent Calendar 2014の12/25のXmasエントリです。
12/24はkinnekoさんによるスマフォでヘッドマウントとか3DVR的にはダメですぜでした。

なんとこの記事は安心と信頼の 野生の男(@yasei_no_otoko) さんに
校正して頂いております!本当にありがとうございます!!

はじめに

Unity Perfomance Best PracticesはGear VRアプリケーションを開発するためのドキュメントですが、
Unityを使ったVRアプリ全般に適用されるような内容となっています。
非常に有益な内容ですので、より多くの人に認知してもらえれば幸いです。


Unity Performance Best Practices

良いパフォーマンスはVRアプリケーションにとってとても重要です。
このセクションでは機能したAndroid Unityアプリを手助けするための簡単なガイドラインを提供します。
このガイドを読む前にDesign GuidelinesのPerformance Advice for Early Titlesというタイトルのセクションをご覧ください。

一般的なCPUの最適化

機能するVRアプリケーションまたはゲームをつくるには、実装方法について熟考しなければならないです。
シーンは常時60fpsで動くべきであり、プレイヤーのガクガクや遅延を回避する必要があります。

  • シーンで使うゲームオブジェクトやコンポーネントの総数に注意する。
  • 効率的にゲームデータとオブジェクトを形成します。大体メモリがたくさんあるでしょう。
  • Update()FixedUpdate()で計算を実行するオブジェクト数を最小限にします。
  • 物理シミュレーションが必要でない場合は減らすか削除します。
  • 頻繁に使用されるエフェクトやオブジェクトを再スポーンするようにオブジェクトプールを使用する、または実行時に新しいものを割り当てます。
  • プールされたAudioSourceか、PlayOneShotではゲームオブジェクトに割り当てられた時に音を鳴らし、削除された時に音声の再生が完了するようにしましょう。
  • 可能な限り、高度な数学的操作は避けてください。
  • キャッシュは、頻繁にルックアップの各フレームを避けるために、コンポーネントとトランスフォームを使用します。
  • 必要に応じて負荷の高いコードを特定し最適化するために、Unity Profilerを使ってください。
  • 各フレームを発生するガベージコレクション(GC)の割り当てを特定・除去するためにUnity Profilerを使ってください。
  • 通常の実行時のパフォーマンスの負荷(スパイク)を特定・除去するためにUnity Profilerを使ってください。
  • UnityのOnGUI()コールは使わないでください。
  • ジャイロや加速度センサーを有効にしないでください。Unityの現在のバージョンでは、これらの機能は負荷の高いディスプレイ·コールの呼び出しを引き出します。
  • モバイルアプリとゲーム開発のためのすべてのベストプラクティスは一般的に適用されます。

レンダリングの最適化

アプリを開発する際に心に留めておくべき最重要事項は、最初からパフォーマンスに保守的になることです。

  • ドローコールを少なく保ちます
  • テクスチャー使用量とメモリ帯域幅を意識します
  • ジオメトリの複雑さを最小限にします
  • フィルレートを意識します

ドローコールを削減する

ドローコールの総数を最小限にします。パフォーマンスを維持する目標としては1フレームあたりドローコールは100未満になるでしょう。
Unityではバッチングやカリングなどのドローコールを減らすため、いくつか標準の機能を提供しています。

ドローコールバッチング

Unityは、実行時にオブジェクトを組み合わせ、単一のドローコールでそれらを描画しようとします。
これはCPUのオーバーヘッドを減らすことができます。スタティック(静的)・ダイナミック(動的)のドローコールバッチングの2種類があります。

スタティックバッチングは、移動、回転、スケールをしない静的なオブジェクトに使われるもので、オブジェクトごとに静的であることを明示的に設定する必要があります。
静的なオブジェクトをマークするには、オブジェクトのInspectorStaticチェックボックスを選択します。


best-practices-1
Unity Pro 4.5

スタティックバッチングはUnity Freeでは使えません。

ダイナミックバッチングは動くことがあるオブジェクトに使用され、特定の条件(同じマテリアルを共有している。リアルタイムシャドウを使ってない。マルチパスシェーダーを使っていない)を満たすオブジェクトに自動的に適用されます。
ダイナミックバッチングの判定基準の詳細については、こちらをご覧ください。
http://docs-jp.unity3d.com/Documentation/Manual/DrawCallBatching.html

カリング

UnityはPer-Layer Cull Disanceにて、カメラのレイヤ毎にカリング距離を手動で設定する機能を提供しています。
一定距離から眺めた時のシーンに関与しない小さいオブジェクトを間引く際に有効でしょう。
カリング距離を設定する方法の詳細については、こちらをご覧ください。
https://docs.unity3d.com/Documentation/ScriptReference/CameralayerCullDistances.html

Unityには統合されたオクリュージョンカリングシステムもあります。
初期のVRタイトルへの忠告としては「オープンワールド」にせず、控えめな「シーン」にすることです。オクルージョンカリングは、控えめなシーンでは過剰かもしれません。
オクルージョンカリングシステムの詳細については、こちらをご覧ください。
(訳注:オクルージョンカリングは不可視オブジェクトが多いシーンでGPUの負荷を減らしますが、判定処理にCPUリソースを消費するため効果が得られない場合は逆に負担となります)
http://blogs.unity3d.com/2013/12/02/occlusion-culling-in-unity-4-3-the-basics/

メモリ帯域幅

テクスチャ圧縮

テクスチャ圧縮は重要なパフォーマンスの利点を提供しています。
ETC2のテクスチャ圧縮形式を支持します。
(訳注:アーキテクチャによって最適なテクスチャ圧縮フォーマットは変わるので、Galaxy Note 4ではETC2が最適ということでしょう)

テクスチャミップマップ

ゲーム内のテクスチャでは常にミップマップを使いましょう。
幸いUnityはインポート時にテクスチャのミップマップを自動的に生成してくれます。
利用できるミップマップのオプションを表示するには、テクスチャのInspectorでTexture TypeをAdvancedに切り替えます。

テクスチャフィルタリング

トリリニアフィルタリングは大抵VRにとっては良い方法です。
パフォーマンスコストがあるが、それだけの価値があります。

異方性フィルタリングを使う方が良いでしょう、しかしフラグメントごとに単一の異方性テクスチャルックアップになるよう保ちましょう。

テクスチャサイズ

ジオメトリの細かさに合わせたテクスチャを使いましょう。
例えば、より多くのポリゴン数を持ったメッシュでは高解像度のテクスチャを使います。我々はテクスチャメモリを豊富に持つことができ、パフォーマンスの視点から見るとそれはほとんど自由と言って良いレベルです。

Asset Storeのテクスチャは、大抵モバイル向けにとって無駄な解像度と言われています。
大抵の場合、明確な見た目の差が出ないままテクスチャのサイズを小さくすることができます。

フレームバッファフォーマット

ほとんどのシーンでは16ビットの深度バッファ解像度で作るべきです。
さらに、あなたの作る世界が圧縮テクスチャでほぼ事前ライティングしている場合には、16ビットのカラーバッファを使用します。

画面解像度

Screen.Resolutionを低い解像度に設定すると、ほとんどのUnityアプリをスピードアップさせることが可能です。

ジオメトリの複雑さを減らす

ジオメトリの複雑さは最小限にします。それぞれの目、視界当たり静的なポリゴン数を5万個にすることが目標です。

モデルの頂点数がモバイル向けであることを確認してください。一般的にAsset Storeのアセットは忠実度が高く作られているので、モバイル向けにチューニングが必要です。

Unity Proではオブジェクトが一定の距離から見られているときに低解像度メッシュにできるようLevel of Detailシステムを搭載しています。(Freeでは使えません)
モデルのLODGroupの設定方法の詳細については、下記を参照ください。
http://docs-jp.unity3d.com/Documentation/Components/class-LODGroup.html

頂点シェーダがモバイル向きであることを確認してください。
組み込みのシェーダを使う場合はMobileかUnlitのものが良いでしょう。

頂点ごとの計算を削減することができるようにテクスチャをベイクしましょう。
例えば、Shadowgunプロジェクトで示されたようなベイク済みバンプマッピングがあります。
https://docs.unity3d.com/430/Documentation/Manual/iphone-PracticalRenderingOptimizations.html

シーン生成時でのゲームオブジェクト数に気をつけましょう。
シーンに多数のGameObjectとRendererがあると、多くのメモリが消費されUnityがシーンの抜粋と描画をするのが長時間になります。

ピクセルの複雑さとオーバードローを削減

ピクセルの複雑さ

できるだけテクスチャに詳細をベイクし、画素毎の計算を削減します。
例えば、フラグメントシェーダでハイライトを計算することを避けるためにテクスチャにスペキュラハイライトを焼き込みます。

フラグメントシェーダがモバイル向きであることを確認してください。
組み込みのシェーダを使う場合はMobileかUnlitのものが良いでしょう。

オーバードロー

Unityの不透明キュー内のオブジェクトはオーバードロー(奥のオブジェクトが描画された後に手前のオブジェクトで無駄に上書きされること)を最小限に抑えるために深度テストを使用して手前から奥の順に描画されます。
しかし、透明キュー内のオブジェクトはオーバードローを前提に奥から手前の順にレンダリングされます。
アルファブレンドされたジオメトリの重なり(例:密度の高いパーティクルエフェクト)とフルスクリーンポストプロセスエフェクトは避けてください。

ベストプラクティス

  • バッチフレンドリーになる
    可能であれば共有マテリアルかテクスチャアトラスを使う
  • ライトマップ、スタティックジオメトリを選びます
  • キャラクターと動くオブジェクトに対して動的ライティングよりLight Probesを選びます
  • 可能な限りテクスチャに詳細をベイクします
    例) 鏡面反射、アンビエントオクルージョン
  • 目ごとに1つのビューだけを描画します
    シャドウバッファ、反射、マルチカメラ設定、その他を無くす
  • レンダリングパスを最小限にします
    動的ライティング無し、ポストエフェクト無し、バッファ解決をしない、シェーダなどでgrabPassを使わないようにする
  • アルファテスト/pixel discard transparencyを避けます
    アルファテストは高いパフォーマンスオーバーヘッドが発生します。可能であればアルファブレンドに置き換えてください。
  • アルファブレンドによる透明度を最小限にします
  • テクスチャ圧縮を使う
    ETC2が好ましいです。
  • メインのフレームバッファにMSAAを有効にしない
    MSAAは目のRender Textureで有効にできます

設計考察

まだ行っていない場合は、Design Guidlineを確認してください。

スタートアップ手順

良いVR体験のためには全てのグラフィックスがユーザーが常に適切な三次元立体画像を見えるようにレンダリングされているべきです。
さらに、ヘッドトラッキングは常に維持されていなければなりません。
アプリケーションの起動時にこれを行う方法の例はSDKExamples のStartup_Sampleシーンで示されています。

  • 黒一色のスプラッシュ画像が表示されるのはできる限り最小時間にします。
  • 3Dロゴと三次元方向のウィジェットとプログレスメーターがある小さなテストシーンは即時ロードされます。
  • スモールスタートアップシーンがアクティブになっている間、メインシーンはバックグラウンドでロードされています。
  • メインシーンのロードが終わったら、スタートシーンはメインシーンへフェードエフェクトによって遷移します。

ユニバーサルメニューの取り扱い

アプリケーションはユニバーサルメニュー立ち上げのために戻るキー長押し、現在のアプリケーションを終了してOculus Homeアプリケーションのメニューに戻るか確認するために戻るキーの短押しを処理する必要があります。

この機能を示している例がSDKExamplesのGlobalMenu_Sampleのシーンです。
アプリケーションメニューのオプションやアクセスの詳細については、ユニバーサルメニューのドキュメントに記載されています。

Unityプロファイリングツール

上記のガイドラインに従っていても、シーンが丸々60fpsに達しないことがあると思います。
次のセクションではAndroidアプリケーションのボトルネックの診断に役立つ、Unityが提供する各種ツールの詳細について説明します。
追加のプロファイリングツールでは、Performance Analysisのドキュメントを参照してください。

Unity Profiler

Unity ProにはProfilerが搭載されています。
Profilerはボトルネックを特定するために役立つフレーム毎のパフォーマンスメトリクスを提供しています。
adbかWiFiを使ってAndroidデバイス上で実行しているアプリケーションのプロファイルを行うことができます。
デバイスのリモートプロファイリングの設定方法の手順については、以下のUnityのドキュメントのAndroidのセクションを参照してください。
http://docs-jp.unity3d.com/Documentation/Manual/Profiler.html


best-practices-2
Unity Pro 4.5

Unityプロファイラは、Rendering・Scripts・Physics・GarbageCollector・VsyncのCPU使用率を表示します。
また、Rendering Statistics(レンダリング統計)、Memory Usage(メモリ使用量・オブジェクト型ごとのメモリ使用量の内訳を含む)、AudioとPhysics Simulationの統計に関する詳細な情報も提供しています。

レンダリング統計を表示する

UnityでGameView上のStatsボタン(下記のスクリーンショットの右上の赤い丸で囲んでいる箇所)を押すと、GameViewでFPSやドローコール、ポリゴン数、頂点数やVRAM使用量などといったリアルタイムレンダリングの統計情報をオーバーレイで表示するオプションを提供します。


best-practices-3
VrScene:Tuscany

GPUオーバードローを表示する

Unityはシーンのオーバードローを表示するための特別なレンダーモードを提供しています。
Scene ViewのControl Barから、Render ModeのドロップダウンからOverDrawを選びます。
このモードでは、半透明の色はオーバードローの「ヒートマップ」を蓄積しています。
彩度の高い部分は多数のオーバードローが行われていることを表しています。


best-practices-4
VrScene:Tuscany

出典
Oculus Mobile SDK for Samsung Note 4 (Samsung Gear VR), Unity Performance Best Practices
https://developer.oculus.com/downloads/#version=0.4.0

最後に

完璧な監訳、誠にありがとうございます!
この記事を読んだ方は島根に足を向けて寝ないようにしてください。


Posted in Gear VR, Oculus Rift, Unity.