Cornfox & Bros. が明かす、モバイル ゲームを Switch に移植する方法

Senior Graphics Programmer Kalle Hämäläinen
こんにちは、私は KalleHämäläinen です。『Oceanhorn 2:Knights of the Lost Realm』(失われた王国の騎士たち) でシニア グラフィック プログラマーを務めています。このゲームは、iPhone 6s から最新の MacBook Pro まで、Apple Arcade に対応しているすべてのデバイスのために開発されたものです。この記事では、そのゲームをどのようにして Nintendo Switch に移植させたかについて解説します。
 

私たちは、以下の目標をもって移植を開始しました。
 
  • できるだけ高いレベルのクオリティを維持する。
  • フレームレートの安定を図る。
  • ネイティブの解像度を達成させる (ドックをつなげたモードでは 1080p、ハンドヘルド モードで 720p)。
  • 動的解像度を通じてスーパーサンプル アンチエイリアシングを利用する。MSAA (iOS で使用されている) や テンポラル アンチエイリアシング (Mac で使用されている) は使わない。
  • PC のレンダラーの代わりにモバイル レンダラーを使用する。レンダリングの機能よりも解像度を優先したかったため。

Switch の移植については、Engine Software 社と共同で作業しました。私たちのウィッシュリストは、比較的低いクロック速度の 3つの CPU コアをもつ Switch のハードウェアからすると、概して難しい注文でした。

最初のイテレーション

Switch の最初のイテレーションの実行速度は、13 fps でした。iOS では、開発中における目標は 30 fps でした。Apple Arcade が初めて発表されたとき、どのデバイスが最も古いものになるのかは、はっきりしていませんでした (最終的には iPhone 6s でした)。30 fps を目標にすることで、私たちは高解像度を維持することができました。そして、最も重要なことに、安定したバッテリー寿命を維持することもできたのです。 

ソリューション

30 fpsで 1 フレームをレンダリングするには 33.3 ミリ秒使えます。しかし残念ながら、試験段階では、1 フレームほぼ 80 ミリ秒かかりました。困りました。ゲームはすでにモバイル デバイス向けに最適化されていました。何か見落としたのでしょうか。実は、かなり多くのことを見落としていたのです。最新の Apple のモバイル デバイスは、Switch よりも強力な CPU を搭載しています。このことが仇となって、リソースを効率的に利用されないケースをかなり見過ごしてしまったのです。私は、ゲームのプロファイリングを開始し、答えを探しました。

コンソールでのゲームとモバイルで実行するゲームは異なります。モバイルでは、パフォーマンスが影響をうけるものは、バックグラウンドのアプリケーション、バッテリー寿命、デバイスの温度です。コンソールでは、安定したパフォーマンスが得られれば、その後ずっとそれが期待できます。

そこで最適化を開始しました。まず、重いブループリントを見つけることからです。そしてそれらを C++ に移植しました。2 日後には、最初のテストから 20 ミリ秒削ぎ落とすことができました。「これほど簡単に結果が出るのなら、手を伸ばせば容易に実現できることが、まだあるのではないか」と私は思いつきました。1 つはすぐにわかりました。5,000 以上のアクタがあるレベルがあったのです。推奨されている数をはるかに超えていました。iOS デバイスならほぼ問題なく処理できますが、Switch では大幅な変更なしには無理です。

私は、これらのアクタのうちいくつが毎フレーム ティックされているのか調べました。その数は 1,000 を超えていました。その上さらに、ティックしているコンポーネントが約 1,500 ありました。これが問題でした。最初にやらなければならないことは、1 フレームあたりのティック数を減らすことでした。私たちは、問題を見つけ、次のようにして時間を短縮しました。
 
  • まったく何もなされずに更新されるアクタ。このようなアクタについては、ティックを完全に無効化するか、ティックの間隔を大幅に短縮しました。
  • オーバーラップを手動でクエリするアクタ。このようなアクタは、リファクタリングすることによって、Overlap イベントを代わりに使用するようにして、そのイベント直後にのみティックを有効化できました。
  • 純粋にビジュアル的なことを行うが、プレーヤーには見えないアクタ。この問題に対処するために、視錐台、距離、動的および静的なオクルージョン カリングを使って、可視的なアクタだけを更新しました。 
  • 何らかの役割があるため、厳密には目に見えるけれども、遠すぎて目立たないアクタ。たとえば、ホワイト シティには、いつでも合計 300 人を超えるキャラクターがいますが、プレイヤーの範囲内にいるのは 10 人ほどにすぎません。更新が必要なのはそれらのアクタだけです。

Unreal Engine は、これらを最適化する方法をいくつか提供してくれます。ただし、賢い判断をするのはチームの責任です。たとえば、選択したりカスタムのコードが必要になる場合があります。今回の移植のために、私たちはいくつかのコードを追加または削除しましたが、ビルトインされている最適化も利用しました。たとえば、アニメーションのティックレートも使用しました。
低速化の原因はもう 1つありました。それは、Landscape のグラス (草) システムによるものでした。このシステムは、何百万もの草やフォリッジのメッシュをランドスケープ上に動的に生成します。それにより、1 フレームあたり最大で 2.5 ミリ秒消費することが判明しました。私たちは、各ランドスケープレイヤーにさまざまな種類のフォリッジを使用していたのですが、このやり方をとるならば、多数の空のバッチがサポートされることに気付きました。この問題は、簡単に修正できました。特定のフォリッジ タイプごとにコンポーネントのウェイトがゼロである場合、アーリーアウトを追加するのです。また、システムは、ランドスケープのすべてのコンポーネントを更新していました。この問題を修正するためには、まず、あらゆるフォリッジのタイプの最大距離を調べました。そして、次に、その範囲内にあるコンポーネントのみを更新したのです。それによりランドスケープのコンポーネントは、4,000 個から 10 個になりました (プレーヤーの隣にあるコンポーネントです)。レンダリング時間は、0.1 ミリ秒に短縮されました。以上の最適化があなたのプロジェクトにも有効だと思われる場合は、GitHub のこのページこのページ (ログインが必要です) に最新バージョンの Unreal Engine 向けの変更を用意したので是非ご覧ください。 

最後になりましたが、重要なお知らせがあります。Engine Software は、『Sea of Thieves』で使用された Actor Tick Batching と呼ばれるテクニックを実装しました。Actor Tick Batching は、命令のキャッシュミスを減らし、他の最適化の可能性を開きます (重複した作業を削除したり、アクタの距離に基づいてティック レートの最適化を行うなど)。
これらすべての取り組みは、『Oceanhorn 2:Knights of the Lost Realm』の高度に最適化された移植に貢献しています。このゲームは、2020年秋に Nintendo Switch に登場します。お読みいただきまして、ありがとうございました!

    Unreal Engine を今すぐ入手しましょう!

    世界で最もオープンで先進的な制作ツールが入手可能です。 Unreal Engine では、あらゆる機能と完全なソースコードがアクセス可能な状態で入手できるため、すぐに使えます。