LoginSignup
2
0

More than 1 year has passed since last update.

異なるMeshのDrawCall最適化戦略

Posted at

今回の主な話題:異なるMeshのDrawCall最適化戦略、AnimationClipメモリの最適化、レンダリング効果エラー、Unityコンパイル後のエラーをコールバックする可能性、UGUIアトラスの並べる問題。


DrawCall

Q1: Voxelゲームを作成しています。現在、ゲーム内では、すべてのモデルが同じMaterialを共有し、各モデルパーツ(モンスター)は個別のMeshであり、Animatorで作成したアニメーションにはボーンがなく、キーフレームアニメーションであり、GPUインスタンスが有効になっています。

発生した問題:
例えば、一人のキャラクターには10以上のパーツがあり、マップに10種類のモンスターが同時に表示されると、モデルパーツのDrawCallは100以上に急上昇します。現在、特殊効果はあまり追加されていないため、実機(Mi8 Lite)でテストしてもスタッター効果はなく、GPUインスタンスも開いております。種類が少ない、数量が多い場合でも動作が悪くないです。
しかし、私はまだ皆にお聞きたいです。この高いDrawCall問題のための良い最適化方法はありますか?それとも最適化する必要がありますか? 感謝します!
1.png
2.png
3.png

自分でCulling+手動でDrawMeshInstancedをコールする(直接マテリアルでinstanceをチェックすると合併できない場合がよくあります)ことで、パーツ種類と同じ数のDrawCallに減らすことができます

アニメーションの精度要求が高くなく、スペースを時間に変えられる場合、モデルを作成してフレームアニメーションごとにベイクして、DrawMeshInstancedを使用したら、モデル種類と同じ数のDrawCallに減らすことができます。

LWRP / HDRPを使用すると、1つ便利な点があります。SRP batcherを開き、マテリアルのenable instanceをチェックしない(「しない」と注意してください)、自有Shaderを使用する場合、DrawCallの急低下がすぐ見られます。カスタムShaderの場合、書き直すことも難しくないです。


Animation

Q2: 何かアニメーションメモリ占用を最適化する良い方法ありませんか?よく見える精度の低下、圧縮、Scaleの削除などの一般的な操作以外に、frame Rateを下げることで行けますか?

frame Rateに関して、以下のことを補充できます。

問題主の問題が「アニメーションがUnityにインポートした後、再生する時にframe Rateを変更します(アニメーションの再生speedを制御することにより、Unityにインポートした後に実にはアニメーションクリップの元来frame Rateを変更できません)」の場合、frame Rateの変更はメモリに影響しません。

しかし、もし問題主がアニメーション制作ソフトウェア(3ds Max、Mayaなど)でframe Rateを変更することを指す場合、Unityにインポートした後にメモリが実際に影響を受けます。このとき、2つのアニメーションが同じである場合、単純にフレームレートが異なります。

1、アニメーションの圧縮がオフにする場合、実際にキーフレームが多い段落(一般的にはframe Rateの高い部分)のメモリは少し大きくなります。そして他にいくつの影響要因もあります。

a、インポート時にresample curvesをオンにします(このオプションは、インポート時にUnityがフレームを自動的に挿入するかどうかを決定し、再生期間中にすべてのカーブがフルフレームになるようにします。)、frame Rateの高いメモリは高くなります。
b、resampleを開くない場合、frame Rateの高い部分は少し高くなります。

2、Keyframe Reductionなどのアニメーション圧縮を開くと、異なるframe Rateのメモリは再び近くなります(アニメーションが同じであり、実際のアニメーションカーブも類似であるため、圧縮する時に一部の繰り返しデータも同じように圧縮されます)。
結論は、つまり、アニメーション圧縮オプションがオンになっている場合、アニメーションを作成する時のframe Rateがメモリへの影響も大きくないので、特にframe Rateに最適化する必要がありません。

一般的に使用されるiTween、DOTweenプラグインやUWAが推奨するXTweenなど、いくつかの線形アニメーションをシミュレートして、アニメーションキーフレーム設置のデータ量を減らすことができます。


レンダリング

Q3: iPhoneでMetalAPIを使用し、MSAAもオンにします。不透明オブジェクトをレンダリングした後、透明オブジェクトをレンダリングする前のこの階段(例えばAfterForwardOpaque)に、任意1つのCommandBufferを挿入すると、透明隊列の最も前にあるオブジェクトをレンダリングさせ、ZTestはないようです。
注:OpenGL ES3.0の使用に問題はなく、Androidプラットフォームでも問題はありません。

再現用Demoを作成し、iPhoneに構築して実行すれば大丈夫です。MSAAとCommandBufferを同時に開くと、2つの赤いCubeが常に木の前にあることが分かりました。そのうちの1つを閉じたら問題ありません。

再現用Demoを添付します。
MASSDemo.zip

透明オブジェクトをレンダリングした後、不透明オブジェクトをレンダリングする前に1つのCommandBufferを挿入し、このCubeにUnityのディープテクスチャを現在FrameBufferのDeepthBufferに書き込んだら解決できます。


Script

Q4: Unityで、コンパイルするスクリプトがエラーを報告する時にコールバックがあるかどうかを知りたいです。または、使用できるTrickはありますか?

効果を試しました。

public class CompilePostProcesser : AssetPostprocessor
{
static CompilePostProcesser() { EditorApplication.update += Update; }
// すべてのコンパイルが完了した後のコールバック[再帰が発生するように注意してください。つまり、コールバックの操作によって再度コンパイルが発生します]
// コンパイルエラーがある場合、このコールバックは実行されません
[UnityEditor.Callbacks.DidReloadScripts]
private static void OnCompiled()
{
// Debug.ClearDeveloperConsole();
Debug.LogError(“コンパイルが成功しました!);
SuccsccAction?.Invoke();
}
private static void Update()
{
if (EditorUtility.scriptCompilationFailed)
{
EditorApplication.update -= Update;
Debug.LogError(“コンパイルに失敗しました!);
FailAction?.Invoke();
}
}
}

Trickは1つありますが、少し古いです。アイデアは、LogをClearしようとすることです。しかし、コンパイルエラーはClearできないため、コンパイルエラーが発生したかどうかを判断できます。

static void ClearLog()
     {
         Assembly assembly = Assembly.GetAssembly(typeof(SceneView));
         Type logEntries = assembly.GetType("UnityEditorInternal.LogEntries");
         logEntries.GetMethod("Clear").Invoke (new object (), null);

         int count = (int)logEntries.GetMethod("GetCount").Invoke(new object (), null);

         if (count > 0)
             throw new Exception("Cannot build because you have compile errors!");
     }

UI

Q5: Unity 5.6.6バージョンでUGUIを使用してアトラスをパッケージします。スペースは512×512に十分し、各画像のサイズは101×101ですが、17枚の101は512×1024のアトラスにパッケージされます。
4.png
5.png
テストに使用した画像、
6.png

Paddingがあります。両側に1ピクセルのパディングがあるため、101は103になり、512は足りません。

Sprite atlasにはPaddingプロパティがあり、最小は2ピクセル、デフォルトは4ピクセルです。

2ピクセルを例にとると、上記のアトラス画像の高さは512で、4つのテクスチャが占める高さは次のとおりです。2+101+2+101+2+101+2+101=412、残り100ピクセルで、これは垂直方向の5行目のTexureにもう足りません(5行目と4行目の間に2ピクセルのパディングがあることは言うまでもありません)。


UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、パフォーマンス分析最適化ソリューション及びコンサルティングサービスを提供している会社でございます。

UWA公式サイト:https://jp.uwa4d.com
UWA公式ブログ:https://blog.jp.uwa4d.com

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0