
「俺にまかせて」が破綻をまねく!?―スタープレイヤーと仕事の再現性
こんにちは!
今日は「スタープレイヤーと仕事の再現性」というテーマについてお話ししたいと思います。
ゲーム制作現場では、「このプロジェクトはあの人がいないと進まない」といった状況がよくありますよね。
特によくある例は、エース級の開発者が、プレイヤーキャラクターの実装を1人で担当することです。その圧倒的なスキルに頼ることでプロジェクトが進む一方、長期的には大きなリスクを抱えていることがあります。
仕事の属人化:実体験から見る教訓
ベテラン本人しか理解できないプレイヤーコード

あるアクションゲームのシリーズにおいて、長年プレイヤー挙動を1人で担当していたベテランプログラマがいました。そのベテランは、周囲から非常に信頼が厚く、当時はこんな風に語っていました。
「プレイヤーの実装は俺が全部把握してるから、まぁ何かあったら呼んでくれれば、何でも対応するよ。」
確かに、人間的にも技術的にも、すごく頼もしい方だったのですが、ある事件を境に、状況は一変します。
新しく立ち上がる別のプロジェクトをそのベテランが担当することになり、それまで彼が担当していたシリーズの続編では、新しい担当者が彼のコードを引き継ぐことになったのです。
驚くことに、Player.cppには、約8万行ものコードが詰め込まれていました。
関数1つで1000行を超えるケースもザラ。
新しい担当者にとっては、
「ど、どこから手を付けたらいいんだ……?」
という状況です。
そのベテランは、質問をすればすぐに返してくれましたが、業務中いつでも質問をし続けるわけにはいきません。ある程度は、後任者が自分で時間を使って調べないと、仕事が進みません。
そして、シンプルな挙動を追加するだけでも、コード全体を把握しながら慎重に変更する必要があり、大幅な仕様追加は事実上不可能となりました。
続編で進める予定だった新アクションのうちいくつかは、泣く泣く仕様から削除され、代わりにプレイヤー以外のギミックなどを新要素にすることになりました。
後継者は私の先輩でしたが、非常に優秀な方だったので、彼が「できません」と言っている姿を見るのはとても辛かったです。
ギミック担当者の休職

さらに忘れられないのは、私の同期から聞いた話で、ギミック類を担当していたプログラマが休職したときのことです。ギミック担当者は、コードについて口出しされることを嫌っており、周囲がアドバイスしづらい雰囲気を出していたそうです。
実際、彼は作業が非常に早くてバグも少なかったため、周りの人は黙っているしかなかったのです。
「ギミックについては、彼に任せている」
そのチームのリードプログラマは、そう言っていたようです。
しかしある日、彼は家庭の事情で休職することになりました。
私の同期が後任者となり、そのコードを開くと、大変なことになっていました。
クラスの継承構造が5階層以上になっており、どこで何の処理が書かれているのかを把握するのが困難
親クラスの関数を少し変更すると、様々なオブジェクトの挙動に影響が出てしまう。影響範囲は読みづらい。
同じような名前の関数が大量に定義されている
コメントやドキュメントは皆無
任せるという名の、事実上の放置になっていたのです。
結局、私の同期は残業や休日出勤をして彼のコードを解読し、なんとかスケジュールに間に合わせました。同僚からこの話を聞いて、属人化がもたらすリスクを改めて思い知らされました。
コンポーネント指向でよく設計された敵AI

最後に、上手くいった例を紹介します。
とあるプロジェクトで私がコードを引き継ぐことになった敵AIは、これまでの例とはまったく異なる状況でした。担当者が設計をコンポーネント指向で行い、各コンポーネントの役割が明確に分離され、依存関係も切り離されてていました。
また、全体の設計思想や、各コンポーネントの役割を記した詳細なドキュメントも残されていました。
私はこの敵AIを引き継ぎ、わずか数日程度で、追加の実装を開始することができました。2週間後には、自分のコードであるかのようなスピードで実装を進められるようになり、複数の新しい行動を追加実装することにも成功しました。
自分だけ上手くいった例を挙げてしまいましたが、私が特別優秀だったわけではありません。
プレイヤーを引き継いだ先輩や、ギミックを引き継いだ同期は、プログラミング力については私より高かったように思います。
解決策:再現性を高める取り組み
1. 設計の分割とコンポーネント化

プログラムを保守・拡張しやすくする手段として、ソースコードを分割してモジュール化やコンポーネント化をすることが有効です。具体例として、Unreal EngineのGameplay Ability System(GAS) を活用したプレイヤーアクションの実装を挙げます。
たとえば、以下のような構成でプレイヤーアクションを設計できます。
アクションの登録:各アクション(ダッシュ、ジャンプ、スライディングなど)をAbilityとして定義し、実装を分離
タスクの実行:GASのアビリティタスクを用い、呼び出される個別の処理をカプセル化
タグ管理:特定の状態(スタン、無敵など)をGameplay Tagで管理し、条件分岐のハードコーディングを削減
こうした設計により、プレイヤーの挙動をモジュール化し、他の開発者も容易に理解・拡張できるようになります。
2. データ主導の設計
複雑なロジックをコード内に書き込むのではなく、データで管理する仕組みを取り入れることが効果的です。
例えば、Unreal Engine 5では、以下のような仕組みが活用できます。
Chooser:アニメーション選択ロジックをGUI上で定義
State Tree:複雑な状態遷移をビジュアル化
データテーブル:アクションパラメータ(スピード、距離、持続時間など)を外部ファイルで管理
これにより、プログラム内のif文やスイッチ文を大幅に削減し、将来的な拡張にも柔軟に対応できます。
3. 実装のドキュメント化

コード設計や実装については、明確なドキュメントを残すことが必要です。実際に有効だった例として、以下のような構成のドキュメントを作成しました。
全体設計図:クラスやコンポーネントの関係を図示
機能別ガイド:各コンポーネントの役割と使用方法
特殊な処理へのコメント:どうしてもif文が複雑化する箇所などには、経緯を残しておく
ドキュメントを作るのは、プロジェクト終了時や、実際に引継ぎが発生した時で構いません。
ドキュメントがあることで、次回作の開発を円滑に進めることが可能となります。
まとめ
スタープレイヤーの存在はチームに大きな力をもたらしますが、そのスキルに頼りすぎると長期的なリスクが生まれます。
属人化を防ぎ、再現性のある開発を実現するためには、設計の分割、データ主導の設計、ドキュメント化を徹底することが不可欠です。
「今自分が書いているコードは、将来絶対に誰かが引き継ぐ」
この考え方が、未来の同僚を救う第一歩です。
長期的な視点を持ちながら、組織全体で安定した開発ができる体制を目指したいですね!
お読みいただき、ありがとうございました。
気に入っていただけたら、ぜひフォローしていただけると嬉しいです!
Xでも情報発信をしていきますので、よかったら覗いてみてください!