Unity を検索

Unity のワークフロー高速化の舞台裏

2021年7月5日 カテゴリ: Engine & platform | 20 分 で読めます
Black gradient background with a overlay of white graph lines and the words "2021.2 Feature Preview"
Black gradient background with a overlay of white graph lines and the words "2021.2 Feature Preview"
シェア

Is this article helpful for you?

Thank you for your feedback!

ラピッドプロトタイピングは、あらゆるクリエイティブな仕事に不可欠な要素です。このブログ記事では、私たちが Unity エディターのコア部分を最適化するために行っていることをご紹介します。この取り組みは、皆さんがアセットのインポートからプレイ可能なゲームの構築・デプロイまで、制作期間全体を通して迅速に反復作業を行えるようにするためのものです。

プロトタイプから本制作に移行してコンテンツを追加し始め、プロジェクトの規模が大きくなってくると、エディターのパフォーマンスは、チームの全員が生産性を高めるための重要な要素となります。そのため、パフォーマンスと反復の速さは、2021 年の私たちの製品にとって最重要の優先事項の 1 つとなっています。これについては、ロードマップに関する記事でご紹介しています。

アセットワークフロー:インポート、開発、ビルド、配布、読み込み

ほとんどのコンテンツでは、アセットのソースファイルからゲームやリアルタイムアプリケーションで使用できる形式にデータを変換する必要があります。インポートが完了すると、Unity は変換されたファイルとそれに関連するデータをアセットデータベースに保存します。インポート後に、インポーターが使用したファイルがディスク上で変更された場合、Unity はアセットデータベースを更新します。Unity はスクリプトの変更を検出すると、C# ドメインを再読み込みします。プロジェクトをターゲットプラットフォームにデプロイする準備ができたら、Unity のビルドシステムは、プロジェクトをバイナリファイルにパッケージ化して、選択したプラットフォームに配布し、実行できるようにします。

Asset workflow

アセットデータベースは、これらすべてのステップにおいて、信頼性、パフォーマンス、拡張性に優れたアセットインポートパイプラインを実現するための中核となる技術です。

しかし、インポーターや圧縮ツール、エディターのコアとなるコードやビルドパイプラインなど、エディターで反復を行う時間に影響を与えるパズルのピースは他にもいろいろとあります。今回のブログ記事では、Unity 2021.2 を最大限に活用していただくために、これらの分野を担当している人たちに話を聞き、詳しい解説をしてもらいました。

エディターの起動時間の最適化

プロジェクト起動時の Unity の処理の多くをアセットデータベースが担っていることから、アセットデータベースのコードを最適化することでどれだけの効果が得られるかを確認しました。アセットデータベースチームのシニアソフトウェアエンジニアである Javier Abud と Jonas Drewsen は、90 万個のアセットを持つテスト用プロジェクトを皮切りに、ベンチマークフレームワークを共同で開発し、多くの最適化とエディター起動時間の改善を実現しました。また、アセットデータベースへの変更が Unity エディターのパフォーマンスにどのような影響を与えるかを示すメトリクスを収集するプロセスを自動化する一連の社内ツールを共同で開発しました。

「作業を始めてすぐに成果が出た部分もありましたが、もう少し枠にとらわれない考え方を要求される状況がいくつもありました。毎週、テスト用プロジェクトの起動時間を 15 秒ほど削って、そのために加えた変更を 22 個の実プロジェクトに対しても適用し、検証を行いました。大規模なプロジェクトのための最適化が、それより規模の小さな実プロジェクトのパフォーマンスを低下させないことを確認するためです」と Javier Abud は言います。例えば、スレッドやソート時に使うメモリの割り当てを減らしたり、プロジェクトのすべてのファイルとフォルダーを並列処理で収集できる仕組みを導入したりしました。Unity 2021.2 では、90 万個のテキストアセットを持つプロジェクトにおいて、エディターの起動時間を 3 分 36 秒から 1 分 17 秒に短縮したほか、より小さなプロジェクトのプロジェクト起動時間を平均 8.7% 短縮することに成功しました。

インポート

Import Activity ウィンドウ

Javier は「Import Activity ウィンドウ」という新しいツールにも取り組んでいます。このツールを使えば、アセットがインポートされた理由、プロセスにかかった時間、依存関係のためにインポートされやすいアセットなどの情報を得ることができます。詳細はこちらのフォーラム投稿をご覧ください。

モデルとテクスチャ周りの高速化

エディターでの作業できるようになるまで待っている間に何が行われているかを調べてみると、たいていはモデルとテクスチャのインポートに一番時間がかかっていることがわかります。ここでは、Book of the Dead: Environment プロジェクトのすべてのテクスチャ、モデル、プレハブ、シーンをインポートするテストを行います。

Image displaying BOTD Assets import time (PC platform), in seconds and the comparison between 2020 and 2021

このプロジェクトには 2.25GB のソースアセットデータ(テクスチャ 346 枚、モデル 133 体、プレハブ 214 個、シーン 6 つ)が含まれています。AMD ThreadRipper 1950X(16 スレッド)、SSD ストレージの Windows マシンを使い、Unity 2020.3.10、2021.1.9、2021.2 アルファ版(a19)でそれぞれ時間を計測し、比較を行います。

2021.2 アルファ版では、これらのアセットを 114 秒で取り込むことができました(2021.1 と比較して 1.27 倍のスピードアップ)。アセットインポートに 4 つのワーカープロセスを立ち上げ、並列アセットインポートを有効にすると、77 秒でアセットがインポートされます。この設定は、Project Settings → Editor → Refresh にあります。

さらに、Build Settings ウィンドウの Force Fast Compressor オプションを使って反復時間を短縮すると、すべてのアセットをインポートするまでの時間は 38 秒となり、2021.1 バージョンと比較して 3.8 倍のスピードアップとなりました。これは、テクスチャのサイズやフォーマットを変更するものではありませんが、可能な限り圧縮されたテクスチャピクセルを考え出すために費やす労力が少なくなります。

モデルインポートの高速化

最適化チームの Richard Kettlewell は、2021 年のサイクルを通してモデルのインポートを高速化することに注力しています。「様々な問題があり、様々な解決策を検討しましたが、その中でも特に目立ったものがありました」と説明する。「例えば、大規模なメッシュがあると非常に時間がかかる頂点ごとのメモリ割り当ての代わりに、プリパスを実行して必要なメモリの総量をカウントし、1 ブロックで割り当てるアルゴリズムなどです。また、多数のインポートタスクがファイル内のすべてのメッシュ、頂点、アニメーション、マテリアルに対して実行されています。どの部分が独立しているかを判断し、それらを並行して実行するようにすることで大きな成果を得ることができました。」

Richard はさらに、「インポート時に一時的にしか必要としないメモリには、より高速なメモリアロケーターを使用するようにしました」と続けます。「これはあらゆる場所で少しずつ性能の向上をもたらしてくれました。問題のあるモデルを共有するために時間を割いてくれたすべてのアーティストに感謝したいと思います。こうしたテスト向きのコンテンツがなければ、この成果は得られなかったでしょう。」

ファイルに複数のメッシュが含まれている場合、Unity 2021.2 では法線、接線、ライトマップ UV を並列で生成できるようになりました。あるファイルのインポートに 33 分かかっていましたが(そのうち 30 分はライトマップ UV の生成にかかっていました)、このインポートにかかる合計時間を 11 分まで短縮(66% 削減)することができました。複数のメッシュを含むモデルファイルには、この変更による恩恵があります。これらの手順には時間がかかることがあるため、恩恵のあるファイルのインポート時間が大幅に短縮されることが期待されます。

マルチスレッド化されたモデルのインポートステージは他にもあります。

  • FBX アニメーションのインポート
  • 頂点キャッシュオプティマイザーの実行
  • メッシュの三角化(n 角形を三角形に変換)
  • SketchUp の頂点処理

テクスチャインポートの最適化

Quality of Life チームは、2021.1 サイクルでの作業に引き続き、テクスチャのインポート部分を主導しました。2021.2 では、ASTC コンプレッサーを更新し、さらに 30% の高速化と、様々な CPU において信頼性の向上を実現しました。また、BC7 の圧縮は約 2~3 倍の速度になりました。 

また、ビルド設定の Force Fast Compressor オプションもこのチームの取り組みの 1 つです。「テクスチャの品質をあまり気にしないのであれば、テクスチャの圧縮にあまり労力をかけないようにしたり(「Force Fast Compressor」)、テクスチャの最大インポートサイズをグローバルに制限したりすることができます」と Aras Pranckevičius は説明します。「Android ASTC フォーマットで 2 ギガバイトのテクスチャをインポートにこれまで 20 分かかっていたところ、2 分以下でできるようになりました。これの唯一の欠点は圧縮によるアーティファクトが若干増えることです。ですので、これは素早く反復を行いたい時に最適なオプションとなるでしょう。」

Graph displaying the BOTD switch to Android+ASTC, in seconds comparison from 2020.3 to 2021.4

エディター操作を高速化し、フロー状態を維持して開発する

エディターで大規模でフラットなヒエラルキーを持つシーンを開く速度が 90% 以上向上

シーンのルート(Hierarchy ビューのトップレベルにあるゲームオブジェクト)は、リンクリストに順番に格納されているため、読み込みやマージに時間がかかっていました。これまではエディターでシーンを開くと、各ルートオブジェクトが順番にこのリストに追加されていました。シーンからアイテムが読み込まれるとリストに追加され、新しいゲームオブジェクトが追加されるたびに、新しいアイテムを探してリンクリストを走査する必要がありました。これを、新しく追加されたルートオブジェクトの dynamic_array を保存し、リストが必要なときだけソートしてリンクリストにするようにしました。この結果、テスト用のシーンをエディターで開くまでの時間が、17 秒から 1.45 秒へ、90% 短縮されました。

Graph displaying the time to open a scene in editor with a graph comparing before optimization and after optimization on a scale of 10000 to 50000

Unity に対する操作を抑えて、大規模プロジェクトで大きな改善を実現

パフォーマンス最適化チームの主な仕事の 1 つは、顧客や大規模な社内プロダクションと協力して、エディターの操作を高速化できる場所を見出すことです。2、3 秒の待ち時間でも、ゲームが大きくなると問題になります。 

Unity 2021.2 では、Peter Hall が中心となってこの取り組みを行いました。彼は高速化に関する仕事に数多く取り組みましたが、そのうちの 1 つに、大きなシーンで多数のアイテムをドラッグして選択するワークフローの最適化がありました。彼がベンチマークとした社内プロジェクトのある大きなシーンでは、この操作に 78 秒かかっていました。「プロファイラーでキャプチャを取ってみると、大半の時間は、GameObjectTreeViewDataSource.RevealItems から呼び出される BaseHierarchyProperty::Find が使っていることがわかりました。これはヒエラルキーにあるすべての親オブジェクトをルートまでさかのぼって見つける操作ですが、なんとこれをアイテムを 1 つ選択するごとに行っていました。IHierarchyProperty.FindAllAncestors を使用することで、この処理にかかるコストを約 50ms に抑え、1400 倍のスピードアップを実現しました」と語ります。

そのほかにも、新規マテリアルの作成(2 倍高速化)、シーン内の全オブジェクトの選択(1.6 倍高速化)、ゲームオブジェクトのコピーおよびペースト(50% 高速化)など、大規模なプロジェクトにおけるエディター内のワークフローが随所で高速化されています。

ビルド

テストと最適化を始める準備ができたら、どれだけ速くデバイス上で反復して作業できるかが重要になります。そのため、私たちはビルドパイプラインを全体的に最適化するために、多くの時間と労力を費やしています。例えば、Unity 2021.2 では、スクリプタブルビルドパイプラインとビルドキャッシュが高速化されています。

ここでは、プロジェクト全体のサイズではなく、インクリメンタルな変更のサイズに合わせてプレイヤーのビルド時間を調整することが重要なポイントとなります。私達は最近、Unity 自体のビルド方法を改善しましたが、プレイヤーのビルドやスクリプトのコンパイルにもそれと同じツールを導入しています。その結果、Unity 2021.2 ベータ版では、C# スクリプトのインクリメンタルなコンパイルをサポートするソリューションを使って、Windows、macOS、Android、Linux、WebGL の各プラットフォーム向けプレイヤーについて、プレイヤーのインクリメンタルビルドをサポートしています。将来のバージョンの Unity で、この改善を他のプラットフォームに対しても適用するための作業を進めています。

「Unity はプレイヤーをビルドする際に様々なことを行います。まず、すべてのシーンや関連アセット、ゲームマネージャーをシリアライズしてデータファイルにし、プレイヤーデータを構築します。これはネイティブの C++ コードで行われています」とスクリプトチームの Jonas Echterhoff は説明します。「データの構築が終わったら、後処理のメソッドを呼び出します。これは、プラットフォーム固有のマネージドコードです。後処理で何が行われるかはプラットフォームによって異なりますが、通常、プレイヤーのすべてのバイナリと関連ファイルを最終的な位置にコピーしたり、IL2CPP で生成されたコードをネイティブライブラリにコンパイルしたり、プラットフォーム固有の圧縮やパッケージングなどの作業が含まれます。この後処理のロジックは、新しいビルドシステムに移行したものです。」このシステムが各ビルドステップの入出力とそれらの間の依存関係を理解しているので、Unity は実際に再実行する必要のあるステップのみを再実行し、また可能ならば並行して実行します。

IL2CPP のスピードアップ

ビルド設定メニューに新しく追加された IL2CPP コード生成オプションを使うと、完全なジェネリック共有を使って、生成されるコード量を大幅に抑えられるようになりました(最大で 50% 削減)。これにより IL2CPP でビルド時間を削減しつつ、実行形式ファイルのサイズを抑えることが可能になりました。コード生成手法を変えたことにより、実行時のパフォーマンスに若干の影響があるかもしれません。そのため、このオプションはチームが反復を行う時間を短縮する目的で使うのが最も適していると思われます。このオプションを使うことで皆さんのプロジェクトの進行速度がどのくらい上がったかを、こちらのフォーラムスレッドでお知らせいただけると幸いです。

Unity 2020.3 では IL2CPP が大幅に改良され、マルチコアを活用してプレイヤービルド用の C++ コードを生成できるようになりました。「私たちは既存のコードベースで作業していたため、設計上の選択にいくつかの制約がありました。」IL2CPP チームの Michael Voorhees はこのように述べています。「コードベース全体で使用されていた静的なフィールドを削除しなければなりませんでした。そして、うまく並列化できるように、分割統治のパターンにリファクタリングしました。内部の API をリファクタリングすることで、並列と直列の変換モードを維持することができました。これは、低リスクで展開するために重要なことでした。それでも、しっかりとしたストレステストのためのシーンを作り、約 1 か月間、グリーンテストをこなしつつ、デフォルトで並列変換をオンにするのを待ちました」。Unity 2021.1 では、コアの使用率向上と最適化により、変換にかかる時間がさらに短縮されました。

Unity 2021.2 では、コード変換の中でも特にコストのかかるジェネリックコレクションを並列化しました。「新たな最適化の機会を得るために、Cecil を独自のデータモデルに置き換えました。これらの変更に加えて、多くの小さな最適化が行われたことで、Unity 2021.2 の IL2CPP コード変換は Unity 2021.1 の約 2 倍の速さになりました」と Michael は語ります。

Graph 2

その結果、特にモバイル開発者にとっては、ビルド速度が大きく上がりました。例えば、最新の 2D サンプルプロジェクトである「Dragon Crashers」を、Unity 2020 LTS の非インクリメンタルビルドを使って ARMv7 および ARM64 向けにビルドしたところ、簡単なスクリプトの変更で 91 秒かかりました。Unity 2021.2 で新しいインクリメンタルビルドツールを使うと、その半分以下の 44 秒で済みました。

メモリ効率の良いアセットバンドルの読み込み

Image of a virtual underwater scene with a hand holding a recording camera in the bottom right corner
Subnautica プロジェクトには、合計 5199 個のアセットバンドルがあります。

モバイル開発者にとって、動的なコンテンツ配信はこれまで以上に重要になっています。この状況は、実行時のアセットのアーカイブや読み込みを行うために、開発者がアセットバンドルに大きく依存する状況を生み出しています。しかし、同時に読み込まれる個別のアセットバンドルには固定のメモリコストがかかります。このサイズは、実行時のプラットフォームによって 14k バイトから 128k バイトの範囲になることがありました。

この春、アセットパイプラインチームの Kirsten Pilla と Joseph Scheinberg がこの問題に取り組みました。「アセットバンドルごとに専用のキャッシュを用意するのではなく、ページの共有プールを導入しました。」Kristen はこう言います。「アセットバンドルを多数使っている実際のプロジェクトで検証したいと思いました。そこで、Unknown Worlds 社で『Subnautica』の最適化を支援していた Unity Professional Services の Patrick DeVarney と協力しました。」そうして行われた検証では、1,616 個のアセットバンドルが読み込まれた状態で共有ページプールを使うことで、当初 215.7 MBあったオーバーヘッドが 12.9MB にまで減少し、94% という大幅なメモリ使用量削減を達成できることが確認されました。 

また、このメモリ予算を管理するためのシンプルなパブリック API(AssetBundle.memoryBudgetKB)を導入しました。

Diagram with a black background showing how the pooled filecacher system works with assetbundle 1, assetbundle 2, and assetbundle pointing back to the memory cache block pool

今後の予定

反復サイクルの速さは、Unity での仕事をすることの醍醐味の 1 つだという声があります。そのため、顧客のプロジェクトや社内制作のチームの生産性が低下しているという報告がないか、常に注意しています。また、ビルトインとパッケージの両方の機能がエディターでの反復にかかる時間に与える影響を監視するためのより良いツールを構築しています。社内の開発サイクルにおいて、エディターでの反復にかかる時間に関係する主要なパフォーマンス指標を常に把握しておけば、今後のリリースであらゆる規模のプロジェクトの高速化を実現させることができます。

アセットインポートの分野では、長期的な戦略として、アセットをオンデマンドで読み込めるようにして、Unity が必要なものだけを必要な時にインポートできるようにしていきます。また、サポートしているすべてのプラットフォームでインクリメンタルビルドが可能になるように取り組んでいます。次は iOS のサポートが予定されています。

これらすべての領域において、速度に関する皆さんの具体的なニーズを常に踏まえた形で開発を進める最善の方法は、パイプラインと統合のロードマップに関連する領域に皆さんからの提案を追加することです。 

Unity 2021.2 ベータ版へのフィードバック募集中

皆さんのプロジェクトで Unity 2021.2 に施された高速化がどのような働きを示しているかをぜひお聞かせください。Unity 2021.2 は現在ベータ版として提供されています。このバージョンに盛り込まれた改善点については、ベータ版リリースのブログ記事で詳しくご紹介しています。Unity 2021.2 フォーラムに参加して、ご意見をお聞かせください。特に、モデルとテクスチャのインポート新しい IL2CPP コード生成オプションについて、皆さんからのフィードバックをお待ちしております。traVRsal 開発者の Robert Wetzold 氏をはじめ、すでに数値をご提供くださっているアルファテスターの方もいらっしゃいます。まことに感謝いたします。

Unity での全体的な体験に関するフィードバックを送りたい方や、将来の Unity に対する意見がある方は、Unity Pulse にご参加ください。こちらは私たちの新しいリサーチプラットフォームおよびコミュニティで、アンケート、投票、ラウンドテーブル、インタビュー、およびグループディスカッションなど、私たちのリソースをどこに優先的に使うかをより良い形で決めるための活動を行う場所です。

2021年7月5日 カテゴリ: Engine & platform | 20 分 で読めます

Is this article helpful for you?

Thank you for your feedback!

関連する投稿