百鬼無双
Unity
C#
3D Action
1. プロジェクト概要
- ジャンル: 3Dアクション
- 制作期間: 制作中 (修士1年6月から)
- 体制・担当: ソロ制作
- 使用技術: Unity, C#, 3D Action
2. 作品概要
プレイヤーが思い通りにキャラクターを操作でき、「移動しているだけで楽しい」と感じられる最高の手触りを最重視して制作している3Dアクションゲームです。現在は未完成であり、将来的な機能追加や継続的なアップデートを前提として開発を進めています。
3. ゲームの面白さ・体験へのこだわり
本作のコンセプトである「縦横無尽な爽快移動」を最大限に引き出し、プレイヤーに自発的に立体的なアクションを楽しんでもらうため、以下の操作感とゲーム仕様を設計しました。
アクション・操作感の磨き込み
- プレイヤーの直感に寄り添うジャンプ補正(コヨーテタイム) 足場から飛び出した直後でも一定時間ジャンプを受け付けることで、「今なら跳べるはず」という感覚と挙動を合致させています。また、地面付近でのジャンプ入力に対しては2段ジャンプを消費させず通常ジャンプとして扱うよう判定を甘くし、ストレスのない操作感を実現しました。
- 状況を読み取る自然なローリング判定 着地速度や入力状況など複数の条件を組み合わせ、プレイヤーが「勢いよく着地したい」と感じる文脈でのみ、自然にローリングアクションが発生するように調整しています。
- 直感を優先する壁走り(ウォールラン)の移動方向補正 壁走り中にカメラが壁と垂直に近い角度になった際、入力をそのまま物理演算に適用すると僅かなカメラ操作で進行方向がブレて制御不能になる問題がありました。これを防ぐため、一定角度以下になった場合は移動ベクトルを強制的に壁と平行(上方向か下方向)になるよう補正をかけ、人間の感覚に合った滑らかな壁走りを実現しています。
- 物理演算とゲーム性の両立(グラップル操作) 現実の振り子物理をただ適用するのではなく、アクションゲームとしてのレスポンスを最優先しました。ロープがたるんだ状態でも引き寄せ入力がダイレクトに速度へ反映されるよう独自の補正を加え、ロープが張った瞬間には円軌道への正確な速度ベクトル計算と蓄積誤差の修正を行うことで、どんな体勢からでも直感的でスピード感のあるワイヤーアクションを実現しました。
レベルデザインとゲームサイクルの構築
- 空中アクションへ自然に誘導する「部位ダメージ設計」 本作最大の目玉である空中アクションを強制するのではなく、「敵の高い位置(頭など)を攻撃するほど大ダメージを与えられる」仕様にすることで、プレイヤーが自発的にグラップルや壁走りを駆使して「高所を取る(立体的に戦う)」プレイスタイルへと自然に誘導しています。
- 移動を必然にする「バースト湧き」システム 敵がプレイヤーの近くに連続で湧くと定点狩りになり、移動の楽しさが損なわれます。そのため、遠方に敵の群れを一度に生成する「バースト湧き」を採用。群れを殲滅すると次の群れが別の遠方に出現するため、プレイヤーは必然的に「高速で移動するフェーズ」に入り、プレイに心地よい緩急が生まれます。
- プレイのリズムを作るウェーブ制と上達の提示 戦闘の間延びを防ぐためウェーブ制を採用し、明確な区切りによってモチベーションを維持させています。また、難易度が上がる後半ウェーブでは「空を飛ぶ敵」をメインターゲットとして登場させ、プレイヤーが移動操作に習熟したタイミングで培ったテクニックを発揮できる「応用課題」を提示し、大きなカタルシスを生むように配置しています。
4. 技術的な取り組み
- 移動状態とアクション状態の独立管理 キャラクターの「移動ステート」と「アクションステート」を完全に独立して管理するアーキテクチャを構築しました。これにより、移動と様々なアクションをバグなく柔軟に組み合わせることが可能になっています。
- ScriptableObjectによるパラメータの一元化と保守性 各機能の責務を分離し、パラメータはScriptableObjectで公開・一元化しています。基準値を設定し、倍率を掛けて敵の種類ごとのステータスを算出する仕組みを取り入れるなど、プランナー目線での調整作業が容易になる設計を心掛けました。
- オブジェクトプールとイベント駆動によるパフォーマンス最適化
大量の敵が出現する本作において、処理落ちを防ぐため敵の生成にオブジェクトプールを採用し、カクつきを削減しています。さらに、生存数カウントや補充判定などの毎フレーム行う必要のない処理は
Update関数から外し、敵の死亡・デスポーン時にのみ計算が走るイベント駆動アーキテクチャへリファクタリングし、CPU負荷を抑えました。
5. 直面した課題と解決へのプロセス
課題①:アップデートを見据えたシステムの拡張性の確保
- 直面した問題: 今後継続的に武器や敵キャラクター、アクションなどの要素を拡張していく計画の中で、初期の設計のままではコードが密結合になり、機能追加時に予期せぬバグを誘発する恐れがありました。
- 解決プロセス: 前述の通りステート管理を分離させるとともに、武器や敵の挙動をインターフェースで定義しました。ポリモーフィズムを活用することで、既存の処理に手を入れずとも新しい要素を追加できる拡張性の高いアーキテクチャへと設計を見直しました。
- 得られた知見: 設計段階で各機能の責務を明確に分離し、拡張性を担保しておくことで、後からの機能追加が劇的に安全かつスムーズになることを実務レベルで体得しました。
課題②:壁走り判定における直角コーナーでのバグ究明
- 直面した問題: プレイヤーが家の角など、90度になっている壁に向かって壁走りを開始・移行しようとすると、壁の判定が上手く行われず挙動が破綻するバグが発生しました。
- 解決プロセス: デバッガでのブレークポイントの活用に加え、判定用レイ(Raycast)を可視化するビジュアルデバッグを行うことで、角の境界線におけるレイの衝突条件の抜け漏れを特定し、ロジックを修正しました。
- 得られた知見: 3D空間の物理判定が絡むバグにおいては、単なる数値の追跡だけでなく、エディタ上での視覚的なデバッグ(Gizmosやレイの可視化)が原因究明に極めて有効であることを学びました。
課題③:Cinemachineを用いた壁走りカメラとフリールックの両立
- 直面した問題: 壁走り時に画面を傾けるためCinemachineの「Lock To Target」を使用しましたが、プレイヤーを直接ターゲットにするとWASDによる旋回(Yaw回転)にカメラが強制追従してしまい、自由な視点操作(フリールック)が完全に失われる問題が発生しました。
- 解決プロセス: プレイヤーのYaw回転から完全に独立し、「位置」と「壁の傾き(Upベクトル)」だけを同期する中間層クラス(
CameraTargetFollower)を作成し、VContainerで注入しました。プレイヤーの上方向の変化にのみ追従する仮想の正面方向を計算し、状態移行時にCinemachineの入力蓄積をリセットする処理を組み込むことで解決しました。 - 得られた知見: 複雑なカメラ制御においては、対象を直接追従させるのではなく、描画・演出用の中間ターゲット(プロキシ)を挟むことで要件を両立できるという、柔軟な設計アプローチを習得しました。