oc

Unity Performance Best Practices 日本語訳

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

はじめに

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

筆者は英語力に乏しいため、誤訳や一部翻訳出来なかった箇所がございます。
細かいことでも結構ですので、Twitterなどでご指導・ご指摘を頂ければ幸いです。
特に2箇所ほど翻訳に自信がなく、原文ママな所があるので英語に自信のある方は翻訳お願いします(切実)。


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の現在のバージョンでは、これらの機能は負荷の高いディスプレイ·コールの呼び出しを引き出します。
  • モバイルアプリとゲーム開発のためのすべてのベストプラクティスは一般的に適用されます。

レンダリングの最適化

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

  • ドローコールを低くする
  • テクスチャーの使用量と帯域幅に注意する
  • 複雑さを最小限にする
  • フィルレートに注意する

ドローコールを減らす

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

ドローコールバッチング

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

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


best-practices-1
Unity Pro 4.5

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

カリング

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

Unityは統合されたオクリュージョンカリングシステムがあります。
初期のVRタイトルへのアドバイスは「オープンワールド」にせず、控えな「シーン」にすることで、オクルージョンカリングは、控えめなシーンでは過剰かもしれません。
オクルージョンカリングシステムの詳細については、こちらをご覧ください。
http://blogs.unity3d.com/2013/12/02/occlusion-culling-in-unity-4-3-the-basics/

メモリ帯域幅

テクスチャ圧縮

テクスチャ圧縮は重要なパフォーマンスの利点を提供しています。
ETC2のテクスチャ圧縮形式を支持(推奨?)しています。

テクスチャミップマップ

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

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

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

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

テクスチャサイズ

ジオメトリディテールのテクスチャディテールが良いでしょう。
例えば、多くの三角形の高解像度のテクスチャを使う。

テクスチャメモリが沢山あり、パフォーマンスの観点では結構自由である。
Asset Storeのテクスチャは、大抵モバイル向けにとって無駄な解像度です。
あなたは大抵、明確な差がなくテクスチャのサイズを小さくすることができる。

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

ほとんどのシーンで16ビットのデプスバッファの解像度で動くよう作るべきです。
加えて、あなたの世界は主に圧縮テクスチャに予め点灯している場合には、16ビットのカラーバッファを使用することができる。

画面解像度

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

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

ジオメトリの複雑さは最小限にする。
それぞれの目、ビューで静的な三角形を5万個にすることが目標です。
モデルの頂点数はモバイル向けであることを確認してください。
一般的にAsset Storeのアセットは忠実度が高いので、モバイル向けにチューニングが必要です。

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

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

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

シーンを作るときにゲームオブジェクト数に気をつけましょう。
シーンではより多くのGameObjectsとRenderersは、メモリが消費されシーンをレンダリングするためにUnityに掛かるでしょう。

ピクセルの複雑さとOverdrawを削減

ピクセルの複雑さ

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

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

オーバードロー

Unityではオブジェクトの不透明なキューはオーバードローを最小限に抑えるためにデプステストを使用して順序をバックアップする前に描画されます。
しかし、デプステストなしでオーバードローの対象の透明なキュー内のオブジェクトは、後ろから前にレンダリングされる。

ベストプラクティス

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

設計考察

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

スタートアップ手順

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

  • Solid black splash image is shown for the minimum time possible.
  • A small test scene with 3D logo and 3D rotating widget or progress meter is immediately loaded.
  • While the small startup scene is active, the main scene is loaded in the background.
  • Once the main scene is fully loaded, the start scene transitions to the main scene using a fade.

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

アプリケーションはバックキーの長押し操作をする必要があります。

Applications will need to handle the Back Key longpress action which launches the Universal Menu as well as the Back Key shortpress action which launches the ConfirmQuit to Home” Menu which exits the current applicatiom and returns to the Oculus Home application*2.

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

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

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

Unityプロファイラ

Unity Proにはプロファイラが搭載されています。
プロファイラはボトルネックを特定するための各フレームのパフォーマンスメトリクスを提供します。
アプリケーションを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はViewウィンドウ上のStatsボタン(下記のスクリーンショットの右上の赤い丸で囲んでいる箇所)を押すと、GameViewでFPSやドローコールなどといったリアルタイムレンダリングの統計情報ををオーバーレイで表示するオプションを提供します。
Scene ViewのControl Barから、Render ModeのドロップダウンからOverDrawを選びます。


best-practices-3
VrScene:Tuscany

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

Unityはシーンのオーバードローを表示するための特別なレンダーモードを提供しています。
このモードでは、半透明の色はオーバードローの「ヒートマップ」を蓄積している
色がより濃いところでは、オーバードローであることを表している。


best-practices-4
VrScene:Tuscany


*1 シーンを確認して翻訳するのは面倒なので翻訳に力尽きたので、どなたか翻訳お願いします。

*2 ちょっと訳に自信がなかったので原文ママ掲載しています。

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

最後に

翻訳で変なところが沢山あるかと思いますので、ご指摘頂ければ幸いです。
何かあればTwitterでご連絡ください。