Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Unity2018/2019における最適化事情

4,713 views

Published on

2019/9/5に開催されたCEDEC2019の講演スライドです。
講師:黒河優介(ユニティ・テクノロジーズ・ジャパン合同会社)

Unityのイベント資料はこちらから:
https://www.slideshare.net/UnityTechnologiesJapan/clipboards

Published in: Technology
  • Be the first to comment

Unity2018/2019における最適化事情

  1. 1. Unity2018/2019における 最適化事情について
  2. 2. 自己紹介 黒河 優介 エンタープライズコンサルティング デベロッパーリレーションマネージャー・エンジニア ユニティ・テクノロジーズ・ジャパン合同会社
  3. 3. 本講演の内容について • Unity Profiler関連のアップデート情報 • 既存機能でのパフォーマンス向上が見込める変更 • パフォーマンス向上に影響ありそうな新機能
  4. 4. Unity Profiler関連のアップデート情報 • Profilerのアップデート • Profiling関連のPackage Update • Profile Analyzer • Profiler Reader ※下記の 2018年度CEDEC講演で触れた内容については端折ります。 https://www.slideshare.net/UnityTechnologiesJapan/unity-111054310
  5. 5. Profilerのアップデート • 2019.3から、300フレーム制限→2000フレームまで • 2019.3から、HierarchyでMain以外のThread対応 • 2019.3から、IL2CPPでもDeepProfilingサポート • 2018.3から追加されたAPI「Profiler.SetAreaEnable」 • 2019.1から追加されたAPI「FrameMetaData」 • 2019.3でCreateGPUProgram時にShaderのkeywordも取 れるように
  6. 6. 300フレーム制限→2000フレームまで Preferenceから ProfilerWindowのFrameCount を最大2000まで変更することが可能に。 ※Editor側のバッファサイズを変更する
  7. 7. 2000フレームでも足りない場合は… • 300フレーム毎に保存するEditor拡張 https://github.com/wotakuro/UnityProfilerIntervalSave • 実機上で保存したログファイルを分割して読み込む Editor拡張 https://github.com/wotakuro/ProfilerBinarylogSplit ※実機上で保存したログはストレージの許す限り保存されているが ProfilerWindowでの読み出し側が対応していなかったため
  8. 8. Hierarchy ViewのThread対応(2019.3~) 2019.2以前は、MainThrea以外の内容を確認するた めにTimeline表示に切り替える必要があった
  9. 9. Hierarchy ViewのThread対応(2019.3~)
  10. 10. HierarchyでのThread対応(2019.3~) これまでは、リスト表示するHierarchyでは MainThreadしか閲覧できず、別スレッドの処 理を見たい場合はTimeline表示にする必要が あったが、2019.3からは閲覧できるように
  11. 11. Profiler.SetAreaEnable (2018.3~) 上記呼び出しで、実機上でProfilerの ログファイルを書き出しが可能
  12. 12. Profiler.SetAreaEnable (2018.3~) 実機上で保存したログから読み込んだ際、 Memory・Renderingの項目が空の場合は、こ のAPIを叩く必要がある
  13. 13. Profiler.SetAreaEnable (2018.3~) 項目別に有効/無効をセットできるAPI 実機上で書き出したログでCPU以外の項目がデータが 取得できなかった場合は、このAPIを利用して項目を 有効にする必要がある ※ただし CPUを無効にするとProfilerログそのものが 無効になる
  14. 14. 実機のDeepProfilingサポート(2019.3) ビルド時のオプションに Deep Profiling Supportが追加
  15. 15. 実機のDeepProfilingサポート(2019.3) https://forum.unity.com/threads/remote-deep-profile-can-it-be-activated.77801/
  16. 16. FrameMetaData (2019.1~) Profilerで、実行しているフレームに紐づく情報を 別途バイナリ形式で保存が出来るように
  17. 17. FrameMetaData (2019.1~) • マニュアルのサンプルでは、Textureデータを埋め込ん でいる https://docs.unity3d.com/ScriptReference/Profiling.HierarchyFra meDataView.GetFrameMetaData.html • 他にもモバイル端末での温度等を取得してProfilerに載 せる等を行えば、サーマルスロットリングで処理落ち したかどうか等を追う事が可能になる
  18. 18. CreateGPUProgram (2019.3~) 点光源がオブジェクトの範囲内に来た等で ShaderVariantが切り替わった時に、実機上でShaderコ ンパイルが走りProfiler上では「CreateGPUProgram」 という形でスパイクが表れる
  19. 19. CreateGPUProgram (2019.3~) 2019.2以前ではShader名のみしか載らなかったのが、 ShaderのPass名、Keywordも載るようになった
  20. 20. CreateGPUProgram の対策 Shader.CreateGPUProgramのスパイクを避けるためには、 ShaderVariantCollectionを作成し、ロード時のタイミング にShaderVariantCollection.Warmup を呼び出しておく
  21. 21. Profilerそのものではなく Profilingに関するPackageアップデート
  22. 22. Profile Analyzer
  23. 23. Profile Analyzer • ProfilerWindowからUnity APIを使ってデータを引っ 張って来て整理した状況を可視化するツール • Unity 2019.1からPackageManagerに入った • ソースをPackageManagerの管理下よりコピーすれば、 Unity 5.6でも動作可能(※0.4.0-preview時点では)
  24. 24. Profile Analyzer(蛇足) ProfileAnalyzer.csに記述されている部分が ProfilerWindowからデータを抜く部分
  25. 25. Profiler Reader Profilerのログファイルを直接読んで、サマリーのcsvを 作成するEditor拡張 ※直接ログを読むので300/2000フレームの壁はない
  26. 26. Profiler Reader GC Allocが発生した箇所だけ、Sample名と確保量を 抜き出したcsvなどを書き出せる
  27. 27. Profiler Reader Sample一覧を抜き出してcall数や平均呼び出し時間、 1フレーム当たりの時間等をcsvに書き出し
  28. 28. Profiler Reader • 現在 UnityJapanのgithub上で公開 https://github.com/unity3d-jp/ProfilerReader • CUIで ログファイル→csv変換を呼び出す事も考慮 • ユーザー側でも独自にcsvを追加することが可能 • UnityEditorのバージョンアップごとにログファイルの フォーマットがバージョンアップされるので、 ProfilerReaderも都度バージョンアップして対応中
  29. 29. 既存機能のアップデートで最適化された所
  30. 30. 既存機能への最適化 Unityではパフォーマンス測定用の テスト及びレポートする環境を 作って既存機能のパフォーマンス についても考慮しながらアップ デートを行っている https://blogs.unity3d.com/2018/09/25/performance-benchmarking-in-unity-how-to-get-started/
  31. 31. 既存機能への最適化 https://blogs.unity3d.com/2018/09/25/performance-benchmarking-in-unity-how-to-get-started/
  32. 32. 既存機能のアップデート • AnimatorのGameObject非アクティブ化時のリセット対策 • GPU Instancing対応 • TerrainのGPU Instancing対応 • ParticleSystemのGPU Instancing対応 • AndroidでのWorker Threadの調整 • PhysXアップデート
  33. 33. Animatorの非アクティブ化時のリセット対策 • 「Animator.keepAnimatorControllerStateOnDisable」 APIが2018.1~追加 • Trueにすることで、GameObjectのEnable/DisableでAnimatorの ステートを保持し続ける事が可能に • Falseの場合、GameObjectのDisable時にAnimatorの内部バッ ファをクリアしてしまいステート情報が残らない
  34. 34. GPU Instancingについて • 複数の「同一Mesh、Material」のオブジェクトを少な いCPUオーバーヘッドで描画する機能 • DynamicBatchingと違い、CPUでMesh結合処理をしな いで済むのでその分軽い • OpenGLES 2.0、一部のOpenGLES3.0(Adrenoの一部)端 末以外では動作可能 • SystemInfo.supportsInstancing で対応しているか確認 出来る
  35. 35. TerrainのGPU Instancing対応 https://blogs.unity3d.com/jp/2018/10/10/2018-3-terrain-update-getting-started/ 2018.3以降で設定から有効にする ことでInstancing描画をするように
  36. 36. ParticleSystemのGPU Instancing対応 2018.1以降でParticleSystemの RenderModeがMesh時のみ、 Instancing描画の設定項目が追加
  37. 37. ParticleSystemのGPU Instancing対応 Instancingがオフの場合、ParticleSystem内部ではMeshを 結合する処理があり、負荷が大きい。 InstancingオンにすることでMesh結合する処理をせず、 Instancingで描画するので頂点結合の負荷が下がる
  38. 38. ParticleSystemのGPU Instancing対応 ParticleSystemでの頂点結合 処理はJobで行うため WorkerThread側に出ている
  39. 39. ParticleSystemのGPU Instancing対応 Instancing機能を使うためにはShader側も対応が必要 独自のShaderでParticleSystemのGPU Instancing対応を行 う方法は下記マニュアルを参照 https://docs.unity3d.com/ja/current/Manual/PartSysInsta ncing.html
  40. 40. ParticleSystemのGPU Instancing対応 通常のRendererとParticleSystemのInstancingは Shader側のKeywordが異なる。 MaterialのInspectorに出てくるEnable GPU Instancingの項目とParticleSystemのInstancingは 無関係に動作する
  41. 41. AndroidでのWorker Threadの調整 • Androidで5.6 -> 2017.4でAnimator等のテストでハイエ ンド寄りの端末でパフォーマンス劣化があった • モバイル開発チームで、Android SystraceやUnity Profilerを行った • WorkerThreadを作成する際にCPUのLittele Coreの数 を考慮に入れるように処理を変更 • RenderThreadの優先度も変更
  42. 42. PhysXアップデート • Unityの物理演算はPhysXを利用 • UnityのバージョンとPhysXのバージョンは下記の対応 • Unity 5.0~Unity 2018.2 -> PhysX 3.3.3 • Unity 2018.3~Unity 2019.2 -> PhysX 3.4.2 • Unity 2019.3~ -> PhysX 4.1
  43. 43. PhysXアップデート • PhysXのアップデートにより、パフォーマンスの向上 も得られる • その代わりに細かい挙動も変わるので、ゲームの大 部分が物理に依存していた場合にUnityのバージョン アップの障壁となる可能性がある • CharacterControllerもPhysX機能をWrapperしている だけ
  44. 44. PhysXアップデート • OnCollisionEnter(Collision )等のPhysicsのコールバック で引数があった場合には、呼び出しごとにGC Allocが 発生していた • 2018.3からPhysics.reuseCollisionCallbacksのフラグに よって、GC Allocが発生しない コリジョン時のコール バックが可能になった
  45. 45. [TIPS] PhysX 2017.2から追加された AutoSyncTransformを 外すことでパフォーマンス改善が見込めるケースが ある
  46. 46. [TIPS] PhysX
  47. 47. [TIPS] PhysX Before After
  48. 48. [TIPS] PhysX Physics.Raycast はPhysics側で行う処理。 Physics.Raycast の間で、Transform更新があった場合に Physics側 にSyncすることで、直前に行われたTransform更新を正しく判定処 理することが出来るが、その処理は重い
  49. 49. 新機能(描画系) • Dynamic Resolution • Stripping Scriptable Shader Variants • LWRP • SRP Batcher
  50. 50. Dynamic Resolution • GPU負荷が高いときに、解像度を下げる事でフレーム レートを担保する技術 • 以下の二つの組み合わせで実現される • GPU負荷をランタイムで計測するFrameTimingManager • スケーラブルなバッファを管理するScalableBufferManager
  51. 51. Dynamic Resolution • 実装されたタイミングがプラットフォーム毎に異なる • 2018.3のタイミングでは下記をサポート • Xbox One, PS4, Nintendo Switch, iOS, mac, tvOS (Metal only), Android (Vulkan only), Windows Standalone ,UWP (DirectX 12 only).
  52. 52. Dynamic Resolution • FrameTimingによって取得してきたGPU負荷を、 ScalableBufferManagerを使い解像度変更を行う部分は アプリケーション毎にC#で制御する • https://docs.unity3d.com/Manual/DynamicResolution.html • ScalableBufferManagerで管理されて解像度変更を行わ れるかどうかはCamera/RenderTexture毎に設定が可能
  53. 53. Dynamic Resolutionの導入 適応範囲がRendering解像度のみなので、既に進行中の プロジェクトでも比較的導入しやすい。 ただ OpenGLESは未対応なので、モバイルでは片手落ち
  54. 54. Stripping Scriptable Shader Variants • Unityではビルド時に余計なShader Variantを自動的に 判別して削っていた • 2018.2からアプリケーション開発者側でも判別して削 ることが可能になった https://blogs.unity3d.com/jp/2018/05/14/stripping-scriptable-shader-variants/
  55. 55. Stripping Scriptable Shader Variants Shader SubShader Pass Shader情報と Shader Program
  56. 56. Stripping Scriptable Shader Variants Shader SubShader Pass Shader情報と Shader Program Shaderのステージ(vertex/fragment)、キーワード毎に実体がある。 2018.2からは、ビルドに含むか含まないかをC#のコールバックで 制御できるようになる
  57. 57. Stripping Scriptable Shader Variants
  58. 58. Stripping Scriptable Shader Variants IPreprocessShadersインタフェースを継承して、 OnProcessShaderの IList<ShaderCompilerData> を 操作して、どのVariantをビルドに含めるか選択する
  59. 59. Stripping Scriptable Shader Variants Shaderのメモリ使用量を多かった 場合に検討
  60. 60. Stripping Scriptable Shader Variantsの導入 プロジェクトが利用しているShader Variantsを把握して いる、することが可能な環境であるなら、既存プロジェ クトへの適応はしやすい
  61. 61. LWRP • Scriptable Render Pipelineの実装の内の一つ • 2019.3からは Universal RPとなる • 標準Shaderが、モバイルでも考慮されて作られている • 描画パイプラインのカスタマイズの幅が大きい • ただカメラコールバックが使えなくなるなどポストエ フェクト系は作りなおしが必要になる
  62. 62. LWRP(Universal RP) の導入 Shaderへの対応が必要であったり、Material・ PostEffectの作り直しが必要であり、既存プロジェクト への導入はコストが高い Unityのグラフィック開発の多くのリソースは、既に Universal RPに移っている。これからの新しいプロジェ クトの場合はUniversal RPの検討をオススメ
  63. 63. SRP Batcher • Scriptable Render Pipeline使用状況でかつ、SRP Batcherに対応したShaderでのみ有効 • Materialのセットアップを描画の最初の時に出来る限り 行い、その後のMaterial切り替えを出来る限り抑える • GPU Instancingとの共存は出来ない • Platformによりけりだが、Instancingより速いケース が多い https://blogs.unity3d.com/jp/2019/02/28/srp-batcher-speed-up-your-rendering/
  64. 64. SRP Batcher 色々なデータを先にCBufferに 積んでおいて offset切り替えして 描画する仕組み
  65. 65. SRP Batcherの導入 SRP対応が必要なだけでなく、hlslでShaderの記述の必 要があり、CBufferの定義もUnityに沿った形で行う必要 があり、既存プロジェクトへの導入はコストが高い
  66. 66. 新機能 • PlayerMainLoop • GC制御用のAPI • Incremental GC • DOTS • NativeContainer / C# JobSystem / Burst / ECS • Mesh API v2
  67. 67. PlayerMainLoop • Unity 2018.1から利用可能 • PlayerLoopから余計な処理を削除したり、処理の間に 好きな処理を入れることが可能 • たとえばPhysXを使わないアプリなら、PhysX関連の 処理そのものをループから消すことが可能
  68. 68. PlayerLoopについて MonoBehaviour Updateを処理 Animatorの処理 MonoBehaviour LateUpdateを処理 Etc....
  69. 69. PlayerLoopについて MonoBehaviour Updateを処理 Animatorの処理 MonoBehaviour LateUpdateを処理 Etc.... LateUpdateは全くないので、この部分の処理を 全て省くという事が出来たり…
  70. 70. PlayerLoopについて MonoBehaviour Updateを処理 Animatorの処理 MonoBehaviour LateUpdateを処理 Etc.... Animatorの処理の前後に特定のC#スクリプトを 差し込むこともできます。
  71. 71. PlayerLoopについて PlayerLoopで設定できるステップはかな り種類が多いです。 どんな種類があるかはProfielrのトップ 階層を見ると何となくわかります。
  72. 72. PlayerMainLoop • Unity 2019.3から、Renderingのみをスキップ制御する API「OnDemandRendering.renderFrameInterval」が追加 • モバイル環境で、ロード画面などの画面更新がない時、 バッテリー消費を抑えることが可能
  73. 73. PlayerMainLoopの導入 Physicsを使わないなどの場合は、既存プロジェクトへ の対応は比較的容易。ただ対応しても見込める効果は薄 い
  74. 74. GC制御用のAPI • Unity 2018.3から、GCを制御するAPI “GarbageCollector” が追加された • GCを一定の間発生させなくするという制御が可能に https://docs.unity3d.com/ScriptReference/Scripting.GarbageCollector.html
  75. 75. GC制御用APIの導入 元々GC Allocが少ない所に対して呼び出す等、GC起こさ ないための最後の砦として有効に使う事で、既存プロ ジェクトへの対応もしやすい
  76. 76. Incremental GC • これまでUnityのGCは、GCが走り始めると作業が完了す るまで止まらず、長い処理スパイクになっていた • Incremental GCでは、GC処理を毎フレーム少しずつ走ら せる事で大きなスパイクを回避する • Unity 2019.1ではExperimentalとして実装、2020辺りから IncrementalGCの方がデフォルトになる https://blogs.unity3d.com/jp/2018/11/26/feature-preview-incremental-garbage-collection/
  77. 77. Incremental GC
  78. 78. Incremental GCの導入 PlayerSettingsへの対応のみなので、対応そのものは容 易。 ただメモリ周りの挙動が変わるので、メモリがカツカツ なプロジェクトの場合対応は慎重に
  79. 79. DOTS • Data Oriented Technology Stack • NativeContainer,C# JobSystem,Burst,ECSなどのデー タ志向型のテクノロジーを総称したもの
  80. 80. NativeContainer • Unity 2018.1から利用可能 • GCとは関係なく確保できるメモリ • C,C++のように new / Disposeを自前で管理
  81. 81. C# JobSystem • Unity 2018.1から利用可能 • Unityが確保したJob用のWorkerThreadを利用して処理 の高速化を図る • アプリごとのC#処理もWorkerThreadで出来るが、 ManagedHeapにアクセスできない等の制約あり • 各機能が徐々にC# JobSystem向けのAPIを提供 • ParticleSystem,Physics,Navimesh等
  82. 82. [TIPS] IJobParallelForTransform • 複数のTransformのrotation/positionを並行して操作す るためのAPI • 同じRootオブジェクトを持つTransformに対して操作 が行われた場合には、その場でSync処理が走るように なっている(※2018.4にて確認)
  83. 83. [TIPS] IJobParallelForTransform Chara 0001~0003は同じ Rootオブジェクト 「Characters」以下の子 供になっている
  84. 84. [TIPS] IJobParallelForTransform Chara0003以下にあるTransformをJob発行して 弄っている最中に、 Chara0002のTransformへア クセスしたときには、同じRootを持つTransform へのアクセスがあったと見なし、発行したJob完 了を待ってから、Chara0002へのTransform処理 が行われる
  85. 85. C# JobSystemの導入 コードを書き換える必要があり。 全てをJobSystemで書くことは出来ないので、出来ると ころから対応していく。 複数キャラクターの揺れモノなど、独立性をもって動い ていて負荷が高いものについては効果が出やすい
  86. 86. Burst • Unity のPackageManagerより配布 • 既にpreview外れている • ILコードより、もっと効率的なコードを書き出す • 関数単位で、適応するか選択可能 • 限定された機能のみのC#を高速化する • 新しいMathライブラリを使う必要あり https://docs.unity3d.com/Packages/com.unity.burst@1.1/manual/index.html
  87. 87. Burst の導入 関数単位での適用になるので、部分的に始めていくこと が可能。 JobSystemで対応した部分に対してBurstを適用してみて 処理が速くなるか見てみる等
  88. 88. ECS • データの連続性を考慮した新しいオブジェクト制御シ ステム • メモリ上で処理したときに効率が良く処理できる • ロードも連続性を考慮しているので速い • プログラミングの書き方がMonoBehaviourと大きく異 なる
  89. 89. ECS • まだ previewという形で PackageManagerから配布 • 2018/2019という時点では、まだまだ発展途上 • ECSは UnsafeなC#で書かれている • Burstで高速化されることが前提にある
  90. 90. ECS の導入 まだまだ previewなので、チャレンジャー向け。 参照関係を解決して処理などはまだ書きにくい。 オブジェクトの独立性が高くて数が多い背景のオブジェ クト辺りからECSを試してみる
  91. 91. DOTS相関図 ECS C# JobSystem Burst NativeContainer ECSはC#JobSystemで 並行処理を行う
  92. 92. DOTS相関図 ECS C# JobSystem Burst NativeContainer C#JobSystemでは Managed Heap 使えないので、利用
  93. 93. DOTS相関図 ECS C# JobSystem Burst NativeContainer 制約があるC#コードで記述 されているのでBurstで最適 コードになることを期待
  94. 94. Mesh API v2 • 2019.3にて、ランタイムでの動的なMesh生成のための APIが更新 • C# のGC Allocしないで、動的Meshの生成が可能
  95. 95. まとめ • Unity Profilerもアップデートしている • 既存機能も変更してパフォーマンス改善している • 新機能をうまく取り込んでパフォーマンス改善!

×