Unityクライアントのパフォーマンス改善の進め方

はじめに

こんにちは、クラスター株式会社のソフトウェアエンジニアのsotanです。今回はUnityクライアントのパフォーマンス改善の取り組みについて紹介します。ユーザーの皆さまに快適な体験を提供できるように、新機能の開発や既存機能の拡張・修正と並行して、パフォーマンス改善に取り組んでいます。具体的な改善点や改善方法を全て紹介することはできないのですが、どのような雰囲気で進めているのかを知ってもらえればと思います。

パフォーマンス改善についての参考文献

Unityアプリケーションのパフォーマンス改善に必要となる基礎知識やノウハウについては、

  • 【Unite 2017 Tokyo】最適化をする前に覚えておきたい技術(docswell, YouTube
  • Unityパフォーマンスチューニングバイブル(GitHub

などを参考にしています。

実機計測

clusterはマルチプラットフォームで提供されていて様々なスペックの端末で使われていますが、パフォーマンス改善点を探したり改善結果を確認したりする時は、最低動作環境のスペックの検証用端末を使って、実機で動作確認と計測を行います。現在は、特にモバイル版(Android、iOS)のパフォーマンスを優先的に見ています。Unity Editorを使っている環境と実機のスペックの違いによって計測結果が大きく異なっていたり、特定のプラットフォームの場合のみ実行される処理が比較的大きなボトルネックになっているケースがあったりするため、特別な理由がない限りは必ず実機で動作確認と計測を行います。

フィーチャーフラグ

clusterの開発では複数の機能開発を同時並行で進めるためにフィーチャーフラグ(Feature Flag)が使われており、開発版ビルドでは、まだリリースされていない開発進行中の機能が有効になっています。パフォーマンス改善点を探す時は、リリース版と同じ状態にFeatureFlagを設定した上で計測・プロファイリングして詳細を調査していきます。開発進行中の新機能のパフォーマンスを調査・検証する場合は、その機能のFeatureFlagも有効にしておきます。

計測・プロファイリング

Unity ProfilerとProfiler Analyzerを使ってパフォーマンス改善点を探していきます。C#スクリプトの処理負荷について調べる場合、プロファイラーマーカーを追加して計測・プロファイリングを行います。全てのメソッドにマーカーを追加した状態でオーバーヘッドを小さく保ちながら計測することは難しいので、まずは負荷の大きい処理が実行されるエントリーポイントを探していきます。MonoBehaviourのイベント関数(Start/Updateなど)はデフォルトでProfilerに表示されるようになっています。その他のメソッドは独自のマーカーを追加しないとProfilerに表示されませんが、clusterではUniRxやZenjectを使っているので、UniRxのSubscribeクラスにマーカーを追加したりZenjectのProfileBlockをDevelopment Buildで使えるようにしたりすることで、エントリーポイントを探しやすくなります。処理負荷の大きいエントリーポイントをある程度まで絞り込めたら、さらにマーカーを追加して詳細を調べていきます。

効果見積

数多くあるパフォーマンス改善点の優先度を判断するため、パフォーマンス改善のための設計・開発を進める前に、実際にどの程度の改善が見込めそうなのかを計測して明らかにしておきます。特定の機能や動作のON/OFFを切り替えるフラグを追加して、フラグを切り替えた時の処理負荷の差を見ることが多いです。特定の機能領域だけに限定せずに全体的に改善点を探していく場合もあるため、まずは大雑把でも良いので、時間と手間をかけすぎない方法で計測します。以下に示す例では、UIの親になっているGameObjectのON/OFFを切り替えるだけという大雑把な方法で、UIの表示・非表示を切り替えた時のAnimationの処理負荷を確認しています。

効果計測

パフォーマンス改善は新機能の開発や既存機能の拡張ではなくバグ修正・不具合修正のようなものが多いのですが、FeatureFlagを使って改善前と改善後の処理を切り替えられるようにしておきます。C#で実装されている処理については、FeatureFlagを使った分岐処理と合わせて、計測・プロファイリング用のマーカーを追加しておきます。

Unity ProfilerとProfiler Analyzerを使ってパフォーマンス改善の効果を確認します。Profilerを使って改善前(FeatureFlagがOFFの場合)と改善後(FeatureFlagがONの場合)のデータを記録して、それらのデータをProfiler Analyzerで比較します。

以下に示す例は、UIアニメーションの処理負荷を改善した結果についてPixel3で確認・比較したものです。Animationの処理時間の値を見ると、改善前の計測データの中央値は2.24ミリ秒(1.12ミリ秒+1.12ミリ秒)、改善後の計測データの中央値は1.33ミリ秒(0.57ミリ秒+0.76ミリ秒)となっており、1フレームあたりの処理負荷が約0.9ミリ秒軽減されていることが分かります。

おわりに

今回はUnityクライアントのパフォーマンス改善の取り組みについて紹介しました。ユーザーの皆さまに快適な体験を提供できるように、Unityクライアントのパフォーマンス改善とそのための仕組みづくりに引き続き取り組んでいきたいと思います。