異なるMeshのDrawCall最適化戦略

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


DrawCall

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

発生した問題:

例えば、一人のキャラクターには10以上のパーツがあり、マップに10種類のモンスターが同時に表示されると、モデルパーツのDrawCallは100以上に急上昇します。現在、特殊効果はあまり追加されていないため、実機(Mi8 Lite)でテストしてもスタッター効果はなく、GPUインスタンスも開いております。種類が少ない、数量が多い場合でも動作が悪くないです。

しかし、私はまだ皆にお聞きたいです。この高いDrawCall問題のための良い最適化方法はありますか?それとも最適化する必要がありますか? 感謝します!

自分で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(http://t.cn/ESAsElt

透明オブジェクトをレンダリングした後、不透明オブジェクトをレンダリングする前に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を使用してアトラスをパッケージします。スペースは512x512に十分し、各画像のサイズは101x101ですが、17枚の101は512x1024のアトラスにパッケージされます。

テストに使用した画像、

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公式サイト:https://jp.uwa4d.com

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

UWA公式Q&Aコミュニティ(中国語注意)https://answer.uwa4d.com