Unityワークフローのスケーリング:中規模から大規模プロジェクトから得た教訓

Mar 31, 2026
Matthew Wojtechko
Matthew Wojtechko - Mega Cat Studios
Lead Game Developer
Mega Cat StudiosとPlayground Productionsによる『Backyard Baseball』

このブログ投稿はMega Cat Studiosによるシリーズの第1弾であり、彼らのUnityに関する専門知識と、実際の商用ゲーム開発における課題へのソリューションを共有します。入力、レベル、環境デザインを網羅した、このシリーズの他の投稿もぜひご覧ください:

素晴らしいヒントをいくつか持ち帰っていただければ幸いです!

あなたには素晴らしいアイデアがあり、コードは入力するスピードと同じ速さで書き上がっていきます。コミットするたびに、新しい特徴が形作られていきます。しかし、アイデアが形になるスピードこそが、すぐに大規模でバグだらけの混乱した状態を招く原因になりかねません。

Mega Cat Studiosでは、すべてのプロジェクトを情熱を持って開始するため、迅速かつ柔軟に進め、できるだけ早く物事を成し遂げたいという魅力は理解しています。プロトタイプの場合、このアプローチは問題ありません。実際、私たちはそれを推奨しています!賢明な開発者は、いつイテレーションのスピードを優先し、いつ安定性を優先すべきかを知っています。なぜなら、プロトタイプフェーズを終えると、その「迅速かつ柔軟な」アプローチが負債となるからです。

私たちはMega Cat Studiosでこの遷移を何度も経験しており、プロジェクトごとに新しいことを学んでいます。私たちの最新プロジェクトであるBackyard Baseballをローンチに向けて準備する過程で学んだ教訓をいくつか共有したいと思います。

教訓 1:スケールを見据えた構造体

シーンのプレハブ階層は、明確に定義されたグループと親プレハブへの整理を示しており、ナビゲーションを容易にし、効率的な修正を可能にしています。

シーンのプレハブ階層は、明確に定義されたグループと親プレハブへの整理を示しており、ナビゲーションを容易にし、効率的な修正を可能にしています。

スケーリングの問題は、コードの不備が原因であることは稀で、多くの場合、計画性のないアーキテクチャが原因で発生します。開発者やアーティストが 10 秒以内にアセットを見つけられない場合、ワークフローを変更する必要があります。プロジェクトをスケールさせるためのヒントをいくつか紹介します。

  • タイプと目的別に整理する:私たちはタイプ別、次に目的別にグループ化しています。タイプには、アート、コード、オーディオなどのカテゴリが含まれます。目的とは、それらが何のために使用されるかということです。直感的な整理はオンボーディングの摩擦係数を低減します。新しいアーティストは、「Character Idle」スプライトがどこにあるかを、誰かに聞くことなく正確に把握できるはずです。
  • シーンをシンプルに保つ:私たちは「メガシーン」を廃止し、代わりに、セーブデータや重要なシステムを保持するメインシーンや、プレイヤーが試合中かどうかに応じて追加ロードされるタイトル画面や野球のひし形シーンなど、より小さなシーンを採用しています。同様に、自己完結型の機能にはプレハブを使用しているため、変更内容がそれらを含むシーンファイルにシリアル化される可能性が低くなります。これにより、アーティストは環境の作業を行いながら、デザイナーは同じ「レベル」でゲームプレイを調整することができ、ファイル競合が発生しません(これについては後述します)。
  • Addressables システムを設定します:従来の Resources フォルダーの代わりに、Addressables システムを使用して必要なときにのみアセットをロードし、メモリ使用量を抑えています。さらに、Addressables キーを使用してアセットをロードする方が、Resources フォルダー内の特定の場所へのファイルパスを介してロードするよりも明確であり、破損しにくくなります。

難しいのは、これらのベストプラクティスを理解することではありません。開始時にそれらを徹底し、何年も経った後でもその規律を維持することです。

開発のどのフェーズにいるのか、その段階で何を優先しているのかを把握してください。

「プロトタイピングのフェーズでは、コードがほとんどないため、モジュール化する前にまずは機能させることを優先しても問題ありません」と、『Backyard Baseball』の開発者である Paolo Roxas 氏は述べています。「プロジェクトを複雑にする前に、どのようにプレイされるかを確認したいのです。」

Playableなキャラクター、ゲームモード、そして活気あふれる環境の間で、『Backyard Baseball』の膨大な要素を扱うには、優れたアーキテクチャが必要不可欠でした。

Playableなキャラクター、ゲームモード、そして活気あふれる環境の間で、『Backyard Baseball』の膨大な要素を扱うには、優れたアーキテクチャが必要不可欠でした。

レッスン 2:Unityに逆らうのではなく、Unityを活用する

小さく焦点を絞った考慮事項とアクションがプラグアンドプレイで組み合わさり、複雑な守備の決定を形成します。「ゴッド」スクリプトは存在せず、構成可能なビルディングブロックが連携して動作するだけです。

小さく焦点を絞った考慮事項とアクションがプラグアンドプレイで組み合わさり、複雑な守備の決定を形成します。「ゴッド」スクリプトは存在せず、構成可能なビルディングブロックが連携して動作するだけです。

「コンポーネント、ScriptableObjects、カスタムクラスのいずれであっても、焦点を絞った、簡潔で自己完結型のビルディングブロックを作成することほど強力なものはありません」と、Mega Cat Studiosのエンジニアリング責任者であるDavid Chávez Armenteros氏は述べています。Unityはその核心においてモジュール性を採用しています。柔軟性を保つために、私たちは3つの古典的な原則に従っています。

1.単一責任:各スクリプトやクラスは、明確に定義された1つの役割を持つべきです。

2.疎結合:システムは、直接的な参照ではなく、インターフェースやイベントを通じて、適切な場合にのみ相互作用するようにすべきです。循環的または複雑に絡み合ったアーキテクチャを避けるため、コードに実装する前にシステム間の依存関係をグラフ化することをお勧めします。

3.プラグアンドプレイ:広大な「ゴッド」スクリプトを書くのではなく、小さく焦点を絞ったユニットを組み合わせて複雑な動作を作成します。

レッスン 3:制限を利用して自由になる

アセンブリ定義ファイルには、特定のシステムのロジックが含まれており、依存関係が明確に指定されています。図に示すように、Mega Cat Studiosでは、モジュール化と整理を維持するために、多くのアセンブリを使用しています。「循環依存」を導入しないように注意してください。

アセンブリ定義ファイルには、特定のシステムのロジックが含まれており、依存関係が明確に指定されています。図に示すように、Mega Cat Studiosでは、モジュール化と整理を維持するために、多くのアセンブリを使用しています。「循環依存」を導入しないように注意してください。

アセンブリ定義(AsmDefs)は、コードをグループ化するC#の構成要素です。それらの公表されている利点はコンパイル時間の短縮ですが、その隠された最大の強みはモジュール性を強制することです。

リード開発者であり、スパゲッティコードを嫌うニコ・ゴーデンツィは、それらを強く推奨しています。

Backyard Baseballでは、入力レイヤーとゲームプレイレイヤーは異なるDLLにあります。ゲームプレイは、入力の詳細とは完全に無関係です。」

これにより、各依存関係を計算された決定にすることで、エンジニア自身を救うことができます。本当に必要であれば、ゲームパッドの処理からNetcodeまで、プレイヤーの物理演算やAIの動作を壊すリスクを冒さずに、入力システム全体を書き換えることができます。より可能性が高いのは、あるエンジニアがコードベースの単一のドメインで作業できるようにし、誤って別のシステムに変更を連鎖させることを防ぎ、開発者が特徴の実装やバグ修正のために把握しておく必要のあるコードの量を減らすことです。

レッスン4:より賢くテストし、よりハードにテストしない

プロジェクトが成長するにつれて、「ドミノ効果」が支配的になる可能性があります。こちらの小さな変更が、あちらの何かを壊してしまいます。優れたアーキテクチャは非常に役立ちますが、万能薬ではありません。

特徴の変更が手動テストのために品質保証担当の猫たちの手に渡る前に、ゲームは一連の自動化された単位テストで厳密に分析されます。

「テストは要件のリストとして機能します」とニコは言います。「それらは期待される内容を記述し、キーとなるユースケースを提供します。」

Backyard Baseballのキャラクターが速球を投げたり、盗塁したり、ホームランを打ったりするとき、ボールがピッチにふさわしいスピードで移動することを確認したり、ランナーのタイミングが盗塁のメカニズムと一致したり、野手がヒットに正しく反応したりするなど、達成したい特定のゲームプレイの結果があります。キャラクターは地面と正しく衝突する必要があり、ボールは適切なスピードで移動する必要があり、ワインドアップ、スイング、ベース間のスプリントなどのアクションを追跡するプレイヤーコントローラーのフラグのような、より詳細なシステムが機能する必要があります。

パブロ・サンチェスのパワーを調整したり、さらに重要なこととして、バットスイングを制御する共有コードを調整したりする場合、接触のタイミングからボールの軌道に至るまで、すべてのインタラクションがゲーム全体で一貫して動作することを確認する必要があります。

多くの場合、壊れるのは予想外のことであり、それこそがテストが非常に重要である理由のすべてです。

このシステムをワークフローに統合することで、特定の要件が満たされなくなった瞬間にそれを把握できるようになり、干し草の山から針を探すような時間のかかるテストやトラブルシューティングのセッションを削減できます。

UnityのTest Runnerは、システムがモジュール化されている場合に最も効果的に機能します。これが、私たちがアセンブリ定義を使用するもう一つの理由です。

レッスン5:アセットを準備する

このような視覚的なスケーリングエラーは、多くの場合、ワークフローの不具合の兆候です。人為的ミスを防ぐために、開発者はアセットがシーンに入る前にプロジェクトの基準を強制する自動化システムを実装します。

このような視覚的なスケーリングエラーは、多くの場合、ワークフローの不具合の兆候です。人為的ミスを防ぐために、開発者はアセットがシーンに入る前にプロジェクトの基準を強制する自動化システムを実装します。

「過ちは人の常、許すは神の業」

しかし、そもそも人為的ミスを防ぐためのシステムを設定することは、まさに伝説的と言えます。

何時間もコーディングやデバッグを繰り返していると、目がかすんだ開発者が誤ってクリックしたり、一時的なものに過ぎなかった変更を誤ってリポジトリにプッシュしたりすることは避けられません。許容できることではありますが(時折目がかすむ私としてはそう言わざるを得ませんが)、不適切に設定されたインポート設定を持つアセットは、大きな結果を招く可能性があります。多くの開発者は高性能なマシンで作業しているため、最悪のシナリオは、キャラクター、アニメーション、エフェクトを含むスタジアムのシーンが低スペックのハードウェアで動作の遅延や不安定さを引き起こし始めるまで、パフォーマンスの問題に気づかないことです。

このリスクを軽減するために、アセットへのアクセス権を持つユーザーを制限することもできますが、ゲームのコンテンツを調整する必要がある多くの理由から、これがボトルネックにつながります。

  • モデルが大きすぎてカメラの設定に収まりません。
  • このオーディオクリップは音量が小さいため、特定の効果が必要です。
  • シェーダーが変更されたため、すべてのテクスチャを調整する必要があります。

Backyard Baseballのようなゲームでは、視覚的なアイデンティティが重要であり、リリースに向けてルックアンドフィールを完璧にするために、モデルやVFXに何百もの微調整が加えられます。

「どれほど技術的な仕様を定めても、コンテンツの多様性がある以上、異なるアセット間でわずかですが重要な違いに対処しなければならないという事実は避けられません」とNicoは言います。

ここでも自動化が役立ちます。

  • AssetPostprocessor:私たちは、プロジェクトの基準を強制するカスタムインポートロジックを作成しています。
  • OnValidate:私たちはOnValidateメソッドを使用して、エディタ内で欠落している参照をレポートします。これはビルド前に必ず実行されます。

しかし最終的には、自動化の話に気を取られすぎて、手動での修正の方が早い場合にそれを見落とさないようにしてください。

「手作業で10分かかるタスクを自動化するために10日も費やしてはいけません」とDavidは警告します。

レッスン 6:人間という要素(コラボレーション)をマスターする

Mega Cat Studiosでは、開発者は部門を超えて協力し、Version Controlとシンプルなガイドラインを使用して、ゲーム制作中の競合を回避しています。

Mega Cat Studiosでは、開発者は部門を超えて協力し、Version Controlとシンプルなガイドラインを使用して、ゲーム制作中の競合を回避しています。

Version Controlシステム(Gitなど)は、毎日数十人の開発者から寄せられる何百もの変更を調整する際に、真っ先に思い浮かぶツールの一つです。Davidは、Mega Catのすべてのプロジェクトにおいて、以下の実証済みのメソッドを推奨しています。

  • 小さくアトミックな変更:一度に多くのシステムに影響を与える「巨大なコミット」は避けてください。個々の特徴ブランチでの作業は、安定してレビューが完了するまで分離しておきます。個々の変更を個別のコミットに分けることで、履歴が適切に記録され、必要に応じて選択やその他のGitの魔法も使いやすくなります。
  • メインからの日次マージ:特徴ブランチ、部門ブランチ、長期運用ブランチはメインブランチと同期させておきましょう。これにより、最終的なマージの規模と複雑さが軽減され、大規模な競合の防止に役立ちます。
  • マージリクエストのレビュー:これは品質保証の第一線であり、バグの発見、プロジェクト標準の適用、そしてシステム全体との整合性を確保する場です。

「大規模なUnityプロジェクトにおいて、コードレビューは単なる形式ではありません」とDavidは助言します。「それらは競合の防止とプロジェクト全体の品質において重要なキーとなります。」

コードをレビューする担当者が、実装されている領域の専門知識を持ち、コーディングのベストプラクティスを理解していることを確認してください。そうすることで、正確性や保守性を適切に評価できるようになります。

UnityでVersion Controlを可能な限り滑らかなものにするための特定のヒントとコツがあります。シーンとプレハブはプロジェクトの基盤を構成するため、CPUパフォーマンスだけでなく、開発者のコラボレーションのためにも最適化してください。

私たちは常に、巨大なシーンやモノリシックなプレハブよりも、小さく、追加可能で、ネストされたコンポーネントを好みます。こうすることで、開発者は競合することなく並行して作業できます。

シーンやプレハブでのマージ競合は、そのデータが開発者にとって読み取りにくいため、解決が最も難しく、これは重要です。このプロセスを滑らかなものにするために、私たちはこれらのファイルをバイナリではなくテキストとしてシリアル化し、YAMLファイル用のGit設定で自動マージ機能を有効にしています。これにより、Gitがマージ競合を自ら解決する可能性が高まり、新しい特徴を作るという重要な作業のために開発者の時間を確保できます。

しかし、それらすべてにもかかわらず:

「競合を解決しようとするよりも、競合を防ぐ方が通常は優れた戦略です」とNicoは言います。

明確なアセットの所有権は、このために大いに役立ちます。

「誰が特定のシーンやプレハブを変更できるかを定義してください」とDavidは言います。「そうすれば、チームメンバーはアセットを直接編集する代わりに、自分の所有権の範囲外の変更をリクエストするようになります。」

Nicoは同様の手順を「セマフォシステム」と表現しています。これは基本的に、開発者がアセットを変更する際に記録し、実質的にそれを「ロック」するためのスプレッドシートです。別の開発者がそのファイルに変更を加える必要がある場合は、ファイルをロックした開発者が変更をリポジトリにプッシュして「ロックを解除」するまで待つ必要があります。

いつものように、チームにとって最適な手順を見つけてください。

未来のための構築

象徴的なPablo SanchezとMr. Clankyがここにいて、プレイする準備ができています。

象徴的なPablo SanchezとMr. Clankyがここにいて、プレイする準備ができています。

Mega Cat Studiosでは、Unityプロジェクトのスケーリングは「より懸命にコーディングする」ことではなく、アーキテクチャの規律に関することであると学びました。Unityのコンポーネントベースの性質を尊重し、Assembly Definitionsで境界を強制し、将来を見据えてアセットを整理することで、ローンチ前にプロジェクトが技術的負債で崩壊することなく、プロトタイプフェーズのクリエイティブな流れの多くを維持しています。

これらの教訓は重要ですが、完璧なコードベースなど存在しないことを忘れないでください。ソフトウェア開発は、推奨されるプログラミングパターンと実用的な考慮事項が日々衝突する壮大な戦いです。もしこれらの原則のいずれかに従うことで、有益なトレードオフを得られずに開発が停滞するようなら、それは教科書通りの推奨事項ではなく、自身のチームの特性にもっと敏感になる必要があるという兆候です。結局のところ、プロジェクト、チーム、そして人はそれぞれ異なるのです。

私たちはMega Cat Studiosで、日々そのバランスを取るよう努めています。新しいプロジェクトごとに、私たちのゲームライブラリが成長し続ける中で、私たちはより優れたUnity開発者、そしてより優れた協力者になることを目指しています。