プロファイリング
モバイルのための最適化実用ガイド

最適化

Suggest a change

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Close

Sumbission failed

For some reason your suggested change could not be submitted. Please try again in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Close

Cancel

PC と同様にiOS および Android は様々なレベルのパフォーマンスを持ったデバイスがあります。別の電話より10倍のレンダリングが強力な電話は容易に見つかるくらいです。 スケーリングを行う簡単な方法としては:

  1. ベースラインの設定で問題なく実行できることを確認する
  2. 高いパフォーマンスが許容される設定では見映えをあげる:
    • 解像度
    • ポスト プロセッシング
    • MSAA
    • Anisotropy(異方性)
    • シェーダ
    • Fx/パーティクル密度の有効/無効

GPUへのフォーカス

グラフィックス パフォーマンスはフィルレート,ピクセル数,およびジオメトリの複雑さ(頂点カウント)により制約されます。これら3つともレンダラをカリングする方法がみつけられれば削減することが出来ます。オクルージョン カリングがここでは役立つかもしれません。Unity は自動的にビュー Frustum の外にあるオブジェクトをカリングします。

モバイルでは フィルレートの制約(フィルレート = 画面ピクセル数 x シェーダ複雑さ x オーバードロー)があり,複雑すぎるシェーダがもっとも良くある問題です。このためUnity に付属するシェーダを使用するか自身で設計するときはできるだけシンプルにします。もし可能であればピクセルシェーダを頂点シェーダに移行してシンプルにします。

Quality Settings で Texture Quality を下げることでゲームが速くなる場合メモリ帯域幅により制限されている可能性が高いです。テクスチャを圧縮する,ミップマップを使用する,テクスチャ サイズを削減する,等々を行います。

LOD (Level of Detail) - によりオブジェクトをシンプルにするか遠ざかるにつれて完全になくします。主なゴールはドローコール数を削減することです。

グッド プラクティス

モバイルGPUは生成する熱量,使用する電力,大きさや音の大きさに大きな制限があります。このためデスクトップ部品と比較してモバイルGPUは帯域幅が少なく,ALUパフォーマンスが低く,テクスチャリング パワーが劣ります。GPUのアーキテクチャは出来る限り小さい帯域幅で少量の電力を使用するように最適化されてます。

Unity は OpenGL ES 2.0 に最適化されていて,GLSL ES (HLSLと類似) シェーディング言語を使用すさします。ビルトイン シェーダはほとんどHLSL (Cgとも知られる) で書かれています。これはモバイル プラットフォームではGLSL ESにクロスコンパイルされます。直接GLSLを記述することも出来ますが,GLSL->HLSLの変換ツールが現在ないためOpenGL関連のプラットフォームが制限されます(例えば モバイルおよびMac)。HLSLでfloat/half/fixed型を使用するとGLSL ESではhighp/mediump/lowp 精度表現になります。

良い慣習とすべきことのチェックリストを次に示します:

  1. マテリアル数を出来るだけ少なくします。これによりUnityのバッチングが容易になります。
  2. 個別テクスチャよりもテクスチャ アトラス(サブ画像を含む大きな画像)を使用する。これらのほうがロードが高速であり,ステートの変更が少なく,バッチングと親和性があります。
  3. テクスチャ アトラスや共有マテリアル を使用する場合 Renderer.sharedMaterialRenderer.material の代わりに使用します。
  4. Forward rendering ピクセルライトは負荷が高いです。
    • 可能なかぎりリアルタイムライトの代わりにライトマッピングを使用して下さい。
    • quality settingsでpixel light count を調整します。要は指向性ライトのみがピクセル単位であるべきで,その他はすべて頂点単位とすべきです。これは当然にゲームによってどうすべきか決まります。
  5. Quality SettingsのRender Mode of Lightsで試行錯誤して正しい優先度となるようにします。
  6. カットアウト (アルファテスト)シェーダは本当に必要な場合に限定します。
  7. 画面で使用する透明(アルファブレンド)を最小限にします。
  8. 複数のライトが特定のオブジェクトを照らす状況をあらかじめ避けます。
  9. シェーダパスの全体的な数を削減します(シャドウ,ピクセルライト,反射)。
  10. レンダリングの順番は重要です。一般的には:
    • 完全に不透明なオブジェクトは概ね前から後ろの順
    • アルファテストのオブジェクトは概ね前から後ろの順
    • skybox.
    • アルファブレンドのオブジェクト(必要であれば前から後ろの順)
  11. モバイルでポストプロセッシングは負荷が高いため,慎重に使用します。
  12. パーティクル:オーバードローを削減し,出来る限りシンプルなシェーダを使用します。
  13. メッシュのダブルバッファが毎フレーム更新されます:
void Update (){
  // flip between meshes
  bufferMesh = on ? meshA : meshB;
  on = !on;
  bufferMesh.vertices = vertices; // modification to mesh
  meshFilter.sharedMesh = bufferMesh;
}


シェーダの最適化

フィルレートにより制限されているか判断するのは容易です: 画面解像度を下げるとゲームは速くなりますか? もしそうであれば,フィルレートにより制限されています。

次の手法によってシェーダの複雑さを軽減します:

  • アルファテストのシェーダを避けます。代わりにアルファブレンドの種類を使用します。
  • シンプルで最適化されたシェーダのコードを使用します(Unity出荷時のMobile シェーダと同様に)。
  • シェーダで負荷の高いmath関数の使用を避けます (pow, exp, log, cos, sin, tan, その他)。代わりに事前計算されたルックアップテクスチャを使用することを考えて下さい。
  • 出来る限り低い精度の型を(float, half, fixedin Cg) 使用してベストのパフォーマンスを得ます。

CPU へのフォーカス

ゲームがGPUのピクセル処理により制限されてる場合が良くあります。結果的に,特にマルチコア モバイルCPUで,未使用のCPU処理能力が余ることになります。このためGPU作業を代わりにCPUに付け替えることが効果的です(Unityはこれを全て自動的に行います):メッシュ スキニング,小さいオブジェクトのバッチング,パーティクル オブジェクトの更新など。

これらは盲目的でなく慎重に使用されるべきです。ドローコールにより制限されてない場合,バッチングはパフォーマンスに悪影響であり,カリングの効率を下げるだけでなく,ライトにより影響を受けるオブジェクト数を増やしてしまいます。

グッド プラクティス

  • モバイルでフレーム毎に数百以上のドローコールを使用しないで下さい。
  • FindObjectsOfType(およびUnityのgetter プロパティ全般)は非常に遅いため意味のある使用方法として下さい。
  • 移動しないオブジェクトのStaticプロパティを有効にしてスタティックバッチングのようなのような内部最適化を許容して下さい。
  • CPUサイクルを大量や消費してオクルージョンカリングおよび優れたソートを行う(Early Z-cullを活用するため)

物理計算

物理計算は重いCPU処理を伴います。エディター プロファイラーによりプロファイリング出来ます。もしCPU上で物理計算の時間がかかりすぎている場合:

  • Time.fixedDeltaTime (Project settings -> Timeにて) を微調整して出来るだけ大きくします。もしゲームが遅い動作であれば,クイックなアクションを求められるゲームよりfixed updateを少なくするのが良いでしょう。クイックなアクションを求められるゲームは計算がより頻繁に必要であり,結果的に_fixedDeltaTime_ を,より小さな値としないとコリジョンが正しく動作しない可能性があります。
  • Physics.solverIterationCount (Physics Manager)。
  • 出来るかぎりクロス オブジェクトを少なく使用します。
  • Rigidbodyの使用を必要な場合に限ります。
  • プリファレンス メッシュ コライダでプリミティブ コライダを使用します。
  • スタティック コライダ(すなわちRigidbodyのないコライダ)はパフォーマンス影響が甚大であるため絶対に動かさないこと。プロファイラで Static Collider.Move と表示されますが実際の処理は Physics.Simulate にあります。もし必要であればRigidBodyを追加して isKinematic に true をセットします。
  • Windows上でNVidiaのAgPerfMon プロファイリング ツールを使用して必要に応じてより詳細が得られます。

Android

GPU

これらはポピュラーなモバイルアーキテクチャです。これはPC/コンソールで両方とも異なるベンダーであり,通常のGPUと異なるGPUアーキテクチャです。

  • ImgTec PowerVR SGX - タイルベース,ディファード:すべてを小さなタイル として(16x16として) レンダリングし,表示されるピクセルのみシェードします。
  • NVIDIA Tegra - Classic: 全てをレンダリング
  • Qualcomm Adreno - タイル: 全てをタイルでレンダリングし,大きなタイルとして(256kとして) 処理します。
  • ARM Mali Tiled: すべてをタイルとして(16x16として) 処理し,レンダリングします。

異なるレンダリングのアプローチを検討してゲームをそれにあわせて設計します。ソートには特別に注目します。開発サイクルの早い段階でサポートする最低限のローエンド デバイスを決めます。ゲームを設計するときにプロファイラを有効にしてテストします。

プラットフォーム固有のテクスチャ圧縮を使用します

さらなる詳細

画面解像度

Androidバージョン

iOS

GPU

PowerVRアーキテクチャ(タイルベース ディファード)のみを気にすれば良い。

  • ImgTec PowerVR SGX。タイルベース,ディファード:すべてをタイル としてレンダリングし,表示されるピクセルのみシェードします。
  • ImgTec PowerVR MBX。タイルベース,ディファード,固定関数 - iPhone 4/iPad 1 デバイス以前のデバイス。

つまり:

  • ミップマップはそれほど必要でない。
  • アンチエイリアス および Aniso (異方性)は十分安価で, iPad 3 では場合により必要がない

また 欠点として:

  • もしフレーム毎の頂点データ(頂点数 × 頂点シェーダ後の必要ストレージ)がドライバにより割り当てられた内部バッファを超えると,シーンは “分割” される必要がありパフォーマンスが消費されます。ドライバがそれ以降,さらに大きなバッファを割り当てるか,頂点カウントを減らす必要があるかもしれません。これは iPad 2 (iOS 4.3) において10万 頂点でかなり複雑なシェーダにおいて顕著となります。
  • タイルベース ディファード レンダリング(TBDR) はより多くのトランジスタをタイリングおよびディファード部分に割り当てる必要があり,概念的には “生のパフォーマンス” に割り当てられるトランジスタが少なくなります。TBDR で GPU タイミングを得ることは難しく,プロファイリングが難しくなります。

さらなる詳細

画面解像度

iOSバージョン

ダイナミック オブジェクト

アセットバンドル

  • アセットバンドルはある制限までデバイス上にキャッシュ
  • エディター API を使用して作成
  • 読み込みにWWW APIを使用する: WWW.LoadFromCacheOrDownload またはリソースとして AssetBundle.CreateFromMemory や AssetBundle.CreateFromFile を使用する
  • Unload using AssetBundle.Unload. There is an option to unload the bundle, but keep the loaded asset from it. Also can kill all the loaded assets even if they’re referenced in the scene
  • Resources.UnloadUnusedAssets unloads all assets no longer referenced in the scene. So remember to kill references to the assets you don’t need. Public and static variables are never garbage collected.
  • Resources.UnloadAsset unloads a specific asset from memory. It can be reloaded from disk if needed.

iOS 上でアセットバンドルの同時ダウンロード数の制限はありますか?(例えば, 同時に(または毎フレーム)10個のアセットバンドルを安全にダウンロードできますか?)

ダウンロードは OS により提供される 非同期API により実装されているため,OS がいくつのスレッドがダウンロードで作成する必要があるか判断します。複数の同時ダウンロードを起動するとき,デバイスがサポートできる帯域幅の合計および空きメモリ量を頭に入れる必要があります。各々の同時ダウンロードにより一時バッファが割りあてられるため,メモリが不足しないように注意すべきです。

Resources

  • Assets need to be recognized by Unity to be placed in a build.
  • Add .bytes file extension to any raw bytes you want Unity to recognize as a binary data.
  • Add .txt file extension to any text files you want Unity to recognize as a text asset
  • Resources are converted to a platform format at a build time.
  • Resources.Load()

Silly issues checklist

  • Textures without proper compression
  • Different solutions for different cases, but be sure to compress textures unless you’re sure you should not.
  • ETC/RGBA16 - default for android but can tweak depending on the GPU vendor. Best approach is to use ETC where possible. Alpha textures can use two ETC files with one channel being for alpha
  • PVRTC - default for iOS, good for most cases
  • Textures having Get/Set pixels enabled - doubles the footprint, uncheck unless Get/Set is needed
  • Textures loaded from JPEG/PNGs on the runtime will be uncompressed
  • Big mp3 files marked as decompress on load
  • Additive scene loading
  • Unused Assets that remain uncleaned in memory.
  • If it randomly crashes, try on a devkit or a device with 2 GB memory (like Ipad 3).

Sometimes there’s nothing in the console, just a random crash

  • Fast script call and stripping may lead to random crashes on iOS. Try without them.
プロファイリング
モバイルのための最適化実用ガイド