[開発者ノート] 1 vs. 1,000を技術で完成させる
· 著者 Shay · お知らせ

1 vs. 1,000を技術で完成させる
皆さん、はじめまして。Ember & Blade のテクニカルディレクター、Danny です。
今回の開発者ノートでは、小さな開発チームである私たちが挑んだ技術的なチャレンジ、そして Ember & Blade の大規模な 1 vs. 1,000 の無双バトルを支えるエンジニアリングについてお話ししたいと思います。
──────────────────────
1. プロトタイピング
本格的に開発を始める前、最初のプロトタイピング段階で確かめたかったことはただ一つでした。
「3D環境で 1 vs. 1,000 のゲームプレイループは本当に成立するのか?」
子どもの頃に『真・三國無双』(Dynasty Warriors)のようなゲームを遊んで以来、私は果てしなく押し寄せる敵の波を斬り開いて進むアクションゲームに、ずっと強い憧れを抱いてきました。
だからこそ Ember & Blade は、ひとつの明確なミッションを掲げてスタートしました。それは、王道の無双らしい爽快な流れを持ちながら、1 vs. 1,000 の戦いで敵をなぎ倒せる3Dサバイバーライクを作ることです。
2Dであれば、これはそれほど難しい挑戦ではありません。モンスターを1体増やして描画するコストは、スプライトを1枚描く程度で済むからです。しかし3Dでは、これが非常に手強い課題であることがわかりました。
エンティティが1つ増えるたびに、ドローコール、スキニング、影、アニメーション、カリングといったさまざまなコストが一緒についてきます。エンジンに単純に「モブを1,000体スポーンしろ!」と命じれば、深刻なフレーム落ちが起きるのは当然の結果です。
これを技術的に解決することこそが、私たちが思い描いたプレミアムなサバイバーライクの出発点でした。
そこで最初のステップとして、「大量描画」のための最適なアプローチを決めることにしました。
数千ものエンティティのロジックを処理するために ECS(Entity Component System)を、同じメッシュをまとめて一度に描画するために GPU Instancing を、そしてアニメーションをあらかじめテクスチャにベイクしておくために VAT(Vertex Animation Texture)を採用しました。中でも VAT は、私たちが3Dサバイバーライクを作り上げるうえで重要な鍵の一つでした。
次の映像は、ECS、GPU Instancing、VAT を使って900体のモブを描画していた初期のプロトタイプです。
──────────────────────
2. 高パフォーマンスなモンスター描画
私たちが採用した VAT は、アニメーションのブレンドが非常に難しく、アニメーションの数にも厳しい制限があるため、アクションゲームではあまり使われない技術です。
実際、すべてのモンスターをこの方法で最適化してしまうと、ボスやエリートモンスターの重量感や迫力が失われてしまいます。
それは私たちの望むところではありませんでした。
ボスにはソウルライクのボスのように手強く、多彩なパターンを持っていてほしい。その一方で、雑魚敵には気持ちよく吹き飛んでほしかったのです。
求められる要件がこれほど異なるため、モンスターの制作パイプラインを、ランクに応じて2つに分けることにしました。
エリート以上には、スケルタルメッシュと従来のボーンベースのアニメーションを使用しています。この方式はコストが高いものの、出現数が少ないためパフォーマンスへの負荷は十分に許容範囲内であり、クオリティで妥協する必要はありませんでした。
雑魚敵には VAT を使用しています。スケルタルメッシュを処理する代わりに、あらかじめベイクしたアニメーションテクスチャを読み込みます。これによりスキニングのコストは実質的になくなり、同じメッシュ同士はインスタンシングでまとめられて一度に描画されます。
VAT ではアニメーションの種類やブレンドが制限されますが、画面上での主な役割がそもそも「攻撃を受けること」である雑魚敵にとっては、どちらも決定的に重要な要件ではありません。
次の映像では、VAT の導入前後でフレームレートとドローコールがどれだけ改善したかをご覧いただけます。
背景にも同じ原則が当てはまります。画面上を1,000体のモブが駆け回る中で、背景のディテールにまで全力を注ぐだけのパフォーマンス予算は、とても残りませんでした。
メッシュは可能な限り統合し、アセットは積極的に再利用し、遠くにあるオブジェクトは思い切って簡略化しました。プレイヤーの視線はほとんどの場合キャラクターのすぐ周りに集中しているため、ビジュアルの作り込みを画面中央に集中させるという、意識的な選択だと考えていただければと思います。
──────────────────────
3. VFXによる効率の最大化
開発中、私たちが完全に見誤っていたのが視覚エフェクト(VFX)でした。
画面上の1,000体のモンスターさえ何とかできれば大丈夫だろうと考えていたのです。ところが実際に作り始めてみると、戦闘エフェクトやヒットエフェクトは1,000個では収まりませんでした。攻撃が当たるたびにヒットエフェクトが発生し、敵を倒すたびに死亡エフェクトが生まれ、さらにその上から Blessing が絶え間なく降り注ぐ――アクティブな VFX の数は、あっという間に1,000をはるかに超えてしまいました。モンスター自体をどれだけ効率よく描画しても、膨大な量のエフェクトがフレームレートを再び引きずり下ろしてしまうのです。
Unity 標準の組み込みパーティクルシステム(Particle System)は、多くの Unity ゲームで視覚エフェクトを扱う際のデフォルトの選択肢です。しかし、そのシミュレーションは CPU 上で実行されるため、数百個のパーティクルなら見事に動作するものの、数千個単位になると処理しきれなくなります。
この問題を解決するために、私たちは主要なエフェクトを GPU ベースのエフェクトシステムである VFX Graph に移行し、シミュレーションの負荷を事実上 GPU にオフロードしました。GPU は大規模な並列処理を得意としているため、現在サポートできるアクティブなパーティクルの数は、桁違いのレベルになっています。
VFX のワークフローを全面的に変更し、既存のエフェクトをすべてゼロから作り直す必要がある大掛かりな作業でしたが、その成果は下の映像でご自身の目でお確かめいただけます。
このクリップでは、Selaphiel の Blessing の一つである「Crush on You」をご覧いただけます。画面をパーティクルで埋め尽くしながらも、これまで以上に滑らかに動作しています。初期に作られたスキルだったため、幸いにも CPU 駆動の Unity パーティクルシステム版と VFX Graph 版の両方が残っており、比較にはうってつけの例となっています。
さらに私たちは、VFX Graph の最新機能を活用した最適化にも一歩踏み込んで取り組んでいます。最近では、Graphics Buffer による VFX のインスタンシングを導入しました。以前はヒットが発生するたびにエフェクトを個別に複製(Clone)する必要があり、複製によるオーバーヘッドが生じるうえ、インスタンシングも正しく機能しませんでした。現在は Graphics Buffer を使うことで、アクティブな VFX インスタンスを1つだけに保ち、その1つのインスタンスが複数のエフェクトを同時に描画しています。
この最適化の恩恵を最初に受けた Blessing が、Remiel の「Zap Flick」です。映像をご覧いただくとわかるように、カードを1枚ずつ複製して描画する場合と、Graphics Buffer で一度にすべて描画する場合とでは、はっきりとした違いがあります。
──────────────────────
4. 再利用、リサイクル、そして繰り返し
ここまでが「どう描画するか」の話だったとすれば、最後の章は「どう節約するか」の話です。
実は、皆さんが画面上で目にしているものの大部分は、オブジェクトプーリング(Object Pooling)を使って裏側であらかじめ確保されたものです。ダメージ表示、スポーンしたばかりのモンスター、炸裂する VFX――ほぼすべてが絶えず使われ、回収され、再利用されています。
理由はシンプルです。1 vs. 1,000 の戦場では、毎秒何百ものオブジェクトが生まれては消えていきます。これらのオブジェクトを毎回新しく生成しては破棄していたら、ゲームロジックどころではありません。絶え間ないメモリのクリーンアップだけで、ゲームは非常に重くなってしまいます。
そのため、私たちのゲームのモンスターは、倒されても本当の意味で消えることはありません。キューに戻り、次のウェーブで「新しい」モンスターとして再び現れるのです。つまり、皆さんがたった今斬り倒したモンスターが、少し後には別の姿でまたこちらに向かって走ってきているかもしれない、というわけです。
同じ原則は、背景アセットやその他のリソースにも適用されています。背景アセットやテクスチャを複数のエリアで再利用することで、ビルドサイズを軽く保ち、メモリ使用量を減らし、ロード時間を短縮しています。
──────────────────────
おわりに
皆さんに途切れることのない 1 vs. 1,000 の無双バトルを存分に楽しんでいただけるよう、私たちは毎日さまざまな新技術の調査とプロトタイピングを続けています。
たとえば、モダンなグラフィックス API には、PSO(Pipeline State Object)を使ってシェーダーを事前にコンパイルしておくシェーダーウォームアップの手法があり、これは現在も活発に進化を続けている技術です。
現時点ではウォームアップの結果がまだ私たちの理想とするレベルに達していないため、この手法は一部のみ採用しています。しかし今後、Unity からより高度なウォームアップ手法が提供されれば、この技術を積極的に導入していくつもりです。
かつては無謀な挑戦にも思えたものを形にするまでには、数えきれないほどの試行錯誤がありました。そしてこの先も、まだまだ多くの試行錯誤が待っていることでしょう。
こうした取り組みの成果は、9月3日にリリース予定の新しいデモで、実際に体験していただけます。最適化とは本来、目に見えない技術です。うまくいけばいくほど、気づかれなくなるものなのです。皆さんが何も気にすることなく、ただ気持ちよく滑らかに敵を斬り進めることができたなら、それこそが私たちにとって最高の結果です。
これらの最適化のコンセプトについては、Unite Seoul 2026 での講演「Hundreds of Enemies, One Lightweight Build(数百の敵、軽量なビルド)」で詳しくご紹介しました。私たちのエンジニアリングプロセスの裏側を詳しく知りたい方は、ぜひ下の映像をご覧ください。
[Unite Seoul 2026] 수백 마리의 적, 가벼운 빌드:〈엠버 앤 블레이드〉로 만든 3D 뱀서의 비주얼과 최적화
講演スライドは、こちらのリンクからもご覧いただけます:https://nine-lives.dev/insights/unite-2026
パフォーマンスや技術的なアプローチについてのご質問、またはプレイ中に何か問題が発生した場合は、お気軽にコメントを残すか、Discord に参加してお知らせください。より快適な体験をお届けできるよう、これからもパフォーマンスの改善に継続して取り組んでまいります。
最後に、Ember & Blade のロード画面の裏側で、シェーダーウォームアップがどのように実行されているのか、その舞台裏をお見せして締めくくりたいと思います。
— Danny、テクニカルディレクター
タグ: ember-and-blade, devlog