Unity物理エンジンPhysxのパフォーマンスを向上させる方法


今回の主な話題：Unity物理エンジンPhysxのパフォーマンスを向上させる方法、Unityがスクリプトを自動的にコンパイルすることを禁止する方法、Texture2DArrayを使うときにMipmap効果をオンにする。

---
###物理
Q1：Unity物理エンジンPhysxのパフォーマンスを向上させる方法は何ですか？シーンにリジッドボディのある人形オブジェクトを100個入れ、十分に衝突させて、ローエンドマシンでは10フレーム未満しか実行できないことがわかりました。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653855/62187abe-375e-6cba-bcff-3218567f226f.png)
①
>充分な物理計算が必要な場合、これらの小さな人々が混雑していると、多数の物理的衝突が発生する可能性が高く、その結果、物理時間コストが非常に長くなります。
最適化する前に、問題主がいくつかの基本的な物理数値の推奨値を了解する必要があります。すべての設備が100個の自由に作成されたスキンモデルをスムーズに実行できることではありません。
さらに、問題主が実機での具体的な時間かかるボトルネックが本当の物理にかかりますかどうかを確認する必要があります。100個キャラクターがいますから、メッシュの量が多い場合、レンダリングの時間コストも無視できません。Unity Profilerで実機のパフォーマンスのボトルネックを確認することをお勧めします。
最後に、この100個キャラクターの一人一人に正確な物理計算を必要としていますか？光線の交差や距離の判定などの性能/価格比率の高い判定方法で純粋な物理的衝突を置き換えることができますか？これには、問題主がデザインからの視点から考えることが必要です。

②
>PhysX APIを直接コールする方法はないため、所謂物理エンジンのパフォーマンスを最適化することは、実には関連するコンポーネントのパフォーマンスを最適化することです。最初に、RigidBodyではなくCharacterControllerを優先に使用すべきです。次に、MeshColliderの使用を出来る限りに避け、代わりにBoxCollider、SphereCollider、CapsuleColliderを使用してみてください。避けられない場合は、Convexをフックしてください。もちろん、もっとも良い最適化は物理的な衝突を使用しないことです。射線は多くの問題を解決できますが、射線はコストがないではありません。射線のコストはシーン内の面の数に明確に関連しています。もちろん、射線のmaxDistanceとLayerMaskを設定すると、必要のないコストを節約できます。一番いいのは、簡単な物理モデルを使用して問題を記述し、自分でコードを書いて実現することです。

---
###エディター
Q2：何かUnityがスクリプトを自動的にコンパイルすることを禁止する方法はありませんか？
>Preferences > General > Auto Refreshのチェックを外すこともできますが、そうすれば、アセットが外部で変更されても、自動的に再インポートされないため、ある程度の影響があります。
そして、これら2つの関数（EditorApplication.LockReloadAssemblies / UnlockReloadAssemblies）を試すこともできます。ドキュメントを参照してください。
https://docs.unity3d.com/ScriptReference/EditorApplication.LockReloadAssemblie

---
###レンダリング
Q3: Texture2DArrayを使用すると、Mipmap効果がないことがわかりました。Mipmapを効果的にする方法を教えてください。 元のテクスチャはMipmapがオンになっています。

>Texture2DArrayを作成するとき、最後から2番目のパラメーターに注意する必要があります。trueに設定しますと、Mipmapは有効にさせます。ドキュメントを参照してください。
https://docs.unity3d.com/ScriptReference/Texture2DArray-ctor.html

---
###制作
Q4:今は外部で生成された一枚のTextureがmainTexとしてレンダリングできますが、内容を取得して保存したいのに、GetPixelsはTexture2Dの関数なので、そのようなTextureの内容はどうやって取得できますか？

>最初にGraphics.Blitを介して内容をRender Textureに描画し、次にReadPixelsでRenderTextureから一枚のTexture2Dを生成します。sourceTexが元のTexture、tex2Dが最終的なTexture 2Dであると仮定したら、コードは下記のように：

```ruby:
RenderTexture renderTexture = new RenderTexture(sourceTex.width, sourceTex.height, 32);
Graphics.Blit(sourceTex, renderTexture);
Texture2D tex2D = new Texture2D(sourceTex.width, sourceTex.height, TextureFormat.RGBA32, false);
RenderTexture oldRT = RenderTexture.active;
RenderTexture.active = renderTexture;
tex2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
tex2D.Apply();
RenderTexture.active = oldRT;
```

---
###Shader
Q5: TerrainのShaderをカスタマイズしようとしていますが、中にあるShaderの最後にこのような2行があります。この中の「Dependency」は何かできますと聞きたいです。または後に指定されたShaderは何かできますか？
Dependency “AddPassShader” = “Hidden/TerrainEngine/Splatmap/Diffuse-AddPass”
Dependency “BaseMapShader” = “Diffuse”
>Unityのドキュメントはこれの役割を説明すべきではありませんが、このブログでは明確な説明があります。
https://alastaira.wordpress.com/2013/12/07/custom-unity-terrain-material-shaders
これは、Terrainが4つ以上のテクスチャを使用する場合、Unityはこの中のAddPassShaderを使用して二回レンダリングをして、blendします。BaseMapShaderはローエンドのグラフィックスカードで使用され、一枚のテクスチャのみを使用してShaderを表示します。

---
UWA Technologyは、モバイル/VRなど様々なゲーム開発者向け、**パフォーマンス分析**と**最適化ソリューション**及び**コンサルティングサービス**を提供している会社でございます。

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