Unityのパフォーマンスの最適化
プロファイラー
Profiler は Unity が公式に提供している実行効率を検出するツールで、Unity パネルで Ctrl+7 を押すとツールパネルが呼び出されます。
Unityには多くの種類が用意されていますが、よく使われるのはCPU、Rendering(レンダリング)、Memory(メモリ)の3つだけです。
使用手順
CPU モジュールをクリックし、パネルのプロパティを Hierarchy に変更して、簡単なスクリプトを作成してテストを実行します。
public class ProfilerTest : MonoBehaviour
{
void Update()
{
Test();
}
void Test()
{
Debug.Log("AAA");
}
}
プログラムの実行中に、Cpu パネルの任意の場所をクリックすると、下のプロパティ パネルにスクリプトのパフォーマンス消費量が表示されていることがわかりますが、特定のテスト メソッドは表示されていません。この時点で、それをチェックインする必要があります。 [プロファイラー] パネル [ディープ プロファイル] (詳細な検出として理解できます)、[リロード] の順に選択します。
次に、もう一度実行します。
次に、特定のテスト メソッドが表示され、次にテスト内の Debug.log が表示されたことがわかりました。
ディーププロファイル使用時の注意点
DeepProfileを使用するとパフォーマンスが消費されますが、戦闘中や消費量が比較的多い場合にはDeepProfileを使用すると逆効果となるため、避けるべき状況が2つあります。
1: 検出したい機能モジュールを個別に抽出し、個別にテストします。
2: 機能モジュールの結合が激しく、個別に抽出することが難しい場合は、Profiler クラスで提供されるメソッドを使用できます。
public class ProfilerTest : MonoBehaviour
{
void Update()
{
Profiler.BeginSample("Current Profiler");
Test();
Profiler.EndSample();
}
void Test()
{
Debug.Log("AAA");
}
}
プロファイラーは、上記と同じオーバーヘッドである固定メソッドのパフォーマンス消費を検出していることがわかります。
仕事の苦情
私が在宅で仕事をしていた頃、新しくプロジェクトチームが立ち上げられ、メインプロジェクトは実務経験2年未満の研修出身の新人でした。本当に吐きそうになりました。詳細にテストしてほしいということで、彼は簡単なテストを行ったところ、私が書いたスクリプトが比較的高価であることがわかり、それを変更するように私に求められ、その後、ディープ プロファイルを使用して、データ メソッドを保存するために彼を呼び出したことをテストしました。 3MB のオーバーヘッドが発生したので、元に戻すように彼に頼みました。このような同僚に会うのは本当に疲れます。どの仕事もボールを蹴るようなものです。毎回、彼がやりたがる前にリアルタイムでデータを彼の顔に投げつけなければなりません。それから!ただ辞めただけです。
v0.2 バージョン、新しいプロファイラーの導入
最適化は 2 つのカテゴリに分けられます:
レンダリングの最適化 (GPU):
GPU の最適化は主に DrawCall パラメータに対するもので、このパラメータの具体的なパラメータは Baidu である可能性があるため、ここではあまり説明しません。
最も単純な例を挙げると、1G ファイルを別の場所にコピーし、1024 個の 1M ファイルを別の場所にコピーする方が、1G をコピーするよりも確実に高速です。
DrawCallも同様で、DrawCallが呼び出されるたびに、準備作業と事後作業として把握できるので、マージ可能なDrawCallをマージして、準備作業と事後作業の回数を減らす必要があります。
1: 詳細度 LOD テクノロジーは、
距離が異なるとレンダリングされるオブジェクトが異なることを意味します。たとえば、高精度のモデルは近距離でレンダリングされ、低精度のモデルは遠距離でレンダリングされます。
使用される主なコンポーネントは LOD グループです。
3 つのレベルにそれぞれ異なるモデルが追加されます。
2: オクルージョン カリング
レンダリングする必要があるゲーム オブジェクトを
window=》Occlusion に変更します。パラメータを次のように設定します。
ベイクしてカメラを選択して最適化を実現します。つまり、ターゲットの視野内のオブジェクトのみをレンダリングします。
3: ライトマップの結合
詳細については、私のこの記事を参照してください。
ライティングとレンダリング
4: メッシュのマージ
すべてのオブジェクトは 3 つの点と 1 つの側面で構築され、最終的に MeshRender によって描画されますが、多すぎると DrawCall の数が増加するため、メッシュをマージし、レンダリングのためにメッシュに渡すことができます。 。
void MeshCombine()
{
MeshFilter[] filters = GetComponentsInChildren<MeshFilter>();
CombineInstance[] combiners = new CombineInstance[filters.Length];
for(int i = 0; i < filters.Length; i++)
{
combiners[i].mesh = filters[i].sharedMesh;
combiners[i].transform = filters[i].transform.localToWorldMatrix;
}
Mesh finalMesh = new Mesh();
finalMesh.CombineMeshes(combiners);
GetComponent<MeshFilter>().sharedMesh = finalMesh;
}
CPU最適化:
オブジェクトプールの適用など