多くのゲームにとって良いパフォーマンスは決定的なことです。ゲームのグラフィックスのレンダリングのスピードを最大化するための簡単なガイドラインを以下でまとめます。
ゲームのグラフィックな部分は主にコンピュータの2つのシステムにコストがかかります: GPU または CPUです。どんあ最適化であっても最初にやるべきことは パフォーマンスの問題がどこにあるか を見つけることです。GPU と CPUでは最適化の内容はかなり異なります。(場合によっては相反する内容になります - 良くあることとして CPU 最適化で GPU の処理を増やしたり,その逆など)
良くあるボトルネックおよびそれをチェックする方法として:
もちろん,これは原則論です。ボトルネックは他のどこかにあるかもしれません。頻度はやや減りますが,他のボトルネックとして:
画面のオブジェクトをレンダリングするために CPU がやるべきことがいくつかあります - どのライトがオブジェクトに影響するか判断する,シェーダおよびシェーダ パラメータのセットアップ,描画コメンドをグラフィックス ドライバに送信する,次にグラフィックス カードへ送信するコマンドを準備する,等です。これらは “オブジェクト単位” の CPU コストは安価ではないため,表示されるオブジェクトがたくさんある場合,積もり積もってしまう場合があります。
だから例えば,千個の三角形があれば,それらがひとつのメッシュにあるほうが千個のメッシュが個別に三角形があるより安価です。 両方のケースで GPU コストはほぼ同様ですが,CPU が千個のオブジェクトをレンダリングすることはひとつに比べて顕著に差がでます。
CPU の処理量を減らすため,表示されるオブジェクトカウントを減らすのは良い考えです:
オブジェクトをまとめて,各メッシュが少なくとも数百の三角形をもつようにして,メッシュ全体で Material がひとつのみになるようにします。重要なことですが,マテリアルが共通でない二つのオブジェクトをまとめてもパフォーマンスは全く向上しません。複数のマテリアルを使用する一般的な理由は二つのメッシュが同じテクスチャを使用しないためなので, CPU パフォーマンスを最適化するには,オブジェクトをまとめる対象は共通のテクスチャをもつものに絞るべきです。
しかし, Forward Rendering パス でピクセルライトを多く使用する場合,後述するようにオブジェクトをまとめることが無意味な場合があります。
モデル ジオメトリの最適化を行うとき,基本的に二つのルールがあります:
実際にグラフィック ハードウェアが処理すべきは3Dアプリケーションで表示される数と通常は一致しないことに留意して下さい。モデリング アプリケーションは通常ジオメトリ頂点数,すなわちモデルを構成する角の数,を表示します。しかし,グラフィックス カードにとっては,いくつかのジオメトリ頂点は二つ以上の論理的な頂点に分ける必要があります。頂点は複数の法線,UV座標,または頂点カラーがある場合に分割する必要があります。結果的に,Unity の頂点数はつねには3Dアプリケーションで表示される数より大きくなります。
モデルのジオメトリの数が GPU にとってはもっとも関連がある一方で,Unity のいくつかの機能は例えばメッシュスキンのように CPU でモデルを処理します。
計算の必要がないライティングはつねに最速です。 Lightmapping で 毎フレームごと計算するのではなくライティングの “焼き込み” を一回のみ行って下さい。ライトマップ環境を生成するには,Unity上のシーンにライトを配置して,かかる時間はわずかです。 その一方で :
多くの場合,あちこちにライトを配置する代わりに,シェーダおよびコンテンツでのテクニックがあります。例えば,“Rim Lighting” を得るためにカメラに直接を光を差し込むライトの代わりに専用の “Rim Lighting” 計算をシェーダに直接追加することを検討します。
動的な ピクセル ライティング により影響を受けるピクセルに顕著にオーバーヘッドが増加し,オブジェクトが複数のパスでレンダリングすることにつながる場合があります。モバイルやローエンドPCおGPUなど,それほど強力でないデバイスでは,複数の Pixel Light がいずれかのオブジェクトを照らすことは避け,ライトマップを使用して,毎フレームごとに計算させることなく,静的なオブジェクトをライティングして下さい。動的な頂点ライティングも頂点変換により顕著にコストを増加させます。複数のライトがいずれかのオブジェクトを照らすことを避けててください。
もしピクセル ライティングを使用する場合,ピクセライトにより各メッシュが照らされる回数だけレンダリングが行われます。もし二つの離れたメッシュをまとめた場合,まとめたオブジェクトの有効サイズを増やします。このまとめたオブジェクトの一部でも照らす全てのピクセルライトはレンダリングで考慮されるため,レンダリングパスの回数が増えるかもしれません。一般的にまとめたオブジェクトに対するレンダリングは各々の別のオブジェクトのパス回数の合計であり,まとめることにより得られるものはありません。この理由から異なるセットのピクセルライトにより影響されるぐらいに十分に離れたメッシュはまとめるべきではありません。
レンダリングの際に,Unityはメッシュを囲む全てのライトをみつけて,どのライトがそれに最も影響するかを計算します。Quality Settings によりいくつのライトがピクセルライトおよび頂点ライトとして残るかを調整することが出来ます。各ライトはメッシュからの距離および照らす強度にもとづいて各自の重要度を計算します。さらにいくつかのライトはゲームの流れにもとづいて重要度が異なります。この理由から,全てのライトは Render Mode 設定があり,Important または Not Important に設定できます。 Not Important に設定されたライトは一般的により低いレンダリング オーバーヘッドになります。
例としてカーレースのゲームで,プレイヤーの車が暗闇の中でヘッドライトをオンにして走っているとします。ヘッドライトはもっとも重要な光源となるため,Render Mode はおそらくImportant に設定されます。逆に,ゲームの中で重要性がやや劣るもの(他の車のバックライト,等)およびピクセルライトによりビジュアル効果が改善されない場合があります。それらのライトのRender Mode はNot Important に安全にセットすることで,効果が薄いところでは無駄なレンダリングの消費 を避けます。
ピクセル ライティング 最適化は CPU と GPU の両方を節約します: CPU が処理するドロー コールが減り, GPU が処理する頂点数,および,追加のオブジェクト レンダリングでラスタライズするピクセル数が減ります。
圧縮テクスチャ の使用によりテクスチャのサイズを削減(結果的にロードタイムの高速化およびメモリ使用の最小化)し,さらにレンダリング パフォーマンス を飛躍的に向上させる場合があります。圧縮テクスチャは 非圧縮 32ビットRGBAテクスチャと比べるとわずかなメモリ帯域幅しか使用しません。
原則として,3Dシーンで使用されるテクスチャでは Generate Mip Maps を有効化して下さい。圧縮テクスチャにより GPU がレンダリングの際に転送されるテクスチャデータの量を制限するのと同様に,Mip Mapされたテクスチャにより GPU が小さな三角形では低解像度を使用します。
このルールで唯一の例外となるのはテクセル(テクスチャ ピクセル)がレンダリングされた画面ピクセルに 1 : 1 でマッピングする,すなわち UI 要素または 2D ゲームのときです。
いくつかのゲームでは積極的に小さなオブジェクトを大きなオブジェクトと比べて無視し, CPU および GPU ロードを削減することが適切です。例えば,小さな岩や砂塵は遠い距離では透明にして,大きな建物は表示させたままに出来ます。
これは Level Of Detail システムを使用するか,手動で レベル ごとの カリング距離をカメラに設定します。小さなオブジェクトは 別のレイヤー において,レベルごとのカリング距離を Camera.layerCullDistances スクリプト関数をしようしてセットアップできます。
リアルタイム シャドウ は良いけれども,パフォーマンスをかなり消費するものであり,CPU での余分なドロー コール に加えて, GPUで追加の処理を要します。詳細については,シャドウのページ を参照下さい。
ハイエンドPCの GPU および ローエンド モバイル GPU は事実上 100 倍の パフォーマンスの差があります。個々のプラットフォームの中でもバラツキは同様に大きいです。PC 上では,高速な GPU は 遅い統合された GPU より 10 数倍以上 高速です。さらにモバイルプラットフォームでは GPU でも同程度の差が GPU で見られます。
モバイルプラットフォーム でのGPU パフォーマンス および ローエンド PC はあなたの開発機より遥かに遅いものです。一般的には シェーダは手動で最適化して計算量およびテクスチャ読み込みを削減しないと良いパフォーマンスが得られません。例えば,Unityのいくつかのビルトイン シェーダは “モバイル” 同等物があり,より高速です(制限事項や近似はありますが,それらがまさに高速にさせる内容です)。
モバイルやローエンド PC のグラフィックス カードでもっとも重要なのを以下にガイドラインとしてまとめました:
数学的な超越関数( pow, exp, log, cos, sin, tan, その他)はかなり高価であり,原則としてピクセルごとにひとつ以上そういう処理がないようにすべきです。可能なかぎりルックアップ テクスチャで可能なかぎり代替することを考えます。
一方で,カスタムで normalize, dot, inversesqrt の処理を記述して作成することは推奨できません。もし内蔵のものを使用すればドライバがより良いコードを生成してくれます。
アルファテスト(discard)によりフラグメントが遅くなることを頭に入れておいて下さい。
カスタムシェーダを記述するときは浮動小数点はつねに精度を指定すべきです。可能なかぎり最も小さい浮動小数点の形式を選択することはパフォーマンスにとって 決定的 なことです。処理の精度は多くのデスクトップ GPU では無視されますが,多くのモバイル GPU ではパフォーマンスにとって決定的です。
もし シェーダ が Cg/HLSL で記述されている場合,精度は次のように指定されます:
もし シェーダ がGLSL ESで記述されている場合,浮動小数点の精度は各々 highp, mediump, lowp で指定されます。
シェーダ パフォーマンスの詳細については シェーダ パフォーマンス を参照下さい.