まず、この図式はもう「設計図」じゃなくて、ほぼ「OS仕様書」になっている。
ここから先は、どの順番で “遊べる核” を立ち上げるかの問題だけになっている。
次の一手候補(Roblox Studio 前提)
| 候補 | レイヤー | ここから進める意味 | 具体アウトプット |
|---|---|---|---|
| A | 敵AI + 状態遷移 + 階級制度 | このゲームの固有性の中枢。メタ構造が最も濃い | EnemyAIController・状態マシンのSpecとLuaモジュール骨格 |
| B | TimeCycle + Wave + Spawn制度 | 「18時間=45分」のドラマ生成エンジン | TimeCycleService・WaveControllerの連携仕様とイベント設計 |
| C | プレイヤー戦闘(Bow/WebGun/Flight) | 操作感と“空中戦”を先に固める | BowController/WebGunController/FlightSystemの物理&命中ロジックSpec |
推奨ルート:A+Bで「ゲームの一日と戦い」を先に固める
Roblox Studio前提で考えると、
-
メタ構造の芯
敵AIの階級・状態遷移(ScoutElite→Frontline→Officer→General→Royal)
+ TimeCycle + Wave 成長 = 「一日のうちで階級が進化しながら襲ってくる物語」。 -
技術的にも区切りが良い
/src/Server の- EnemyAIController
- EnemySpawnService
- EnemyEvolutionService
- TimeCycleService
- WaveController
を 1 つの「コア・ループ」として定義できる。
これを先に OS として固定しておくと、
後から Player 戦闘や UI を足しても、ゲームの “季節と戦局” は揺れない。
敵AIレイヤーを Roblox 実装に落とす(提案)
ここを次のメッセージで、ほぼそのまま Lua モジュールに写経できる仕様まで落とせる。
1. EnemyTypes / EnemyStats / EvolutionRules
-
EnemyTypes
- 列挙的な ID として
- ScoutElite
- Frontline
- Officer
- General
- Royal
- 列挙的な ID として
-
EnemyStats
- すでに書いてあるテーブルをそのまま
Shared/Modules/EnemyStats.luaとして定義 - Roblox 的には
ModuleScriptでGetStats(enemyType)を返す関数を用意
- すでに書いてあるテーブルをそのまま
-
EvolutionRules
- 「どの条件で Promote されるか」を関数化
- 例:
- 吸血成功回数
- 生存時間
- Wave 番号
ShouldPromote(enemy, context)みたいな形で、- context に
currentTimeSlot,currentWave,carrierHealthなどを渡す。
- context に
2. EnemyAIController(状態マシンの骨格)
-
責務
- 個々の敵に「状態(Idle, Search, Approach, Attack, Promote...)」を持たせ、
tickごと、もしくはHeartbeatごとに状態更新
- 階級ごとに「同じ状態名でも中身が違う」実装をディスパッチする。
- 個々の敵に「状態(Idle, Search, Approach, Attack, Promote...)」を持たせ、
-
設計案
EnemyAIControllerはInitialize(enemyModel, enemyType)SetState(enemy, newState)Update(enemy, dt)
- 状態マシン部は
StateHandlers[enemyType][stateName].EnterStateHandlers[enemyType][stateName].UpdateStateHandlers[enemyType][stateName].Exit
のようなテーブルで外部化。
-
クラス階級メソッドとの対応
- ScoutElite: DetectPlayer, Camouflage, ReportToFrontline
- Frontline: ApproachPlayer, Attack, TryBloodSuck, PromoteToOfficer
- Officer: CommandFrontline, CoordinateAttack, PromoteToGeneral
- General: EvaluateBattle, RetreatOrCharge, ProtectRoyal, PromoteToRoyal
- Royal: EmitPheromones, SpawnFrontline, RelocateAtNight
これらは
- 「状態」=モード(Search / Command / Retreat など)
- 「メソッド」=状態中で呼ばれるサブルーチン
として整理して、StateHandlersの中に収める。
時間制度+Wave制度を接続する(提案)
3. TimeCycleService
-
API
- CurrentTime(0〜18)
- AdvanceTime(dtGameHours)
- OnMorning / OnNoon / OnEvening / OnNight(イベント)
-
ロジック
- 18 ゲーム時間を 45 分にマッピング → 1 分で 0.4 時間進行。
- CurrentTime の値に応じて、
- 朝: 探索エリート大量出現 →
WaveController.SpawnScouts()強化 - 昼: 前線部隊の突撃 →
SpawnFrontline()中心 - 夕: Officer 混じり
- 夜: General / Royal 移動 Wave
- 朝: 探索エリート大量出現 →
4. WaveController
-
API
- StartNextWave()
- SpawnScouts / SpawnFrontline / SpawnOfficers / SpawnGenerals / SpawnRoyal
- TrackRemainingEnemies()(敵が全滅したら次 Wave へ)
-
TimeCycle との接続
- WaveController は TimeCycleService のイベントを購読
- 朝 Wave:ScoutElite 比率高
- 昼 Wave:Frontline 比率高
- 夕 Wave:Officer 増加
- 夜 Wave:General / Royal を混ぜる
- WaveController は TimeCycleService のイベントを購読
-
EnemyEvolutionService との関係
- Wave で出した個々の敵が「吸血成功」などを通じて
Promoteされる。 - WaveController は「スポーン時の階級構成」を決め、
- EnemyEvolutionService は「戦闘結果による階級変化」をハンドル。
- Wave で出した個々の敵が「吸血成功」などを通じて
ここからの具体的な進め方(選択肢)
どのくらい「次のメッセージでそのままコピペできるレベル」まで落としたいかで分かれると思う。
-
A-1: 敵AI状態マシンの Feature Spec → Lua モジュール骨格
/Shared/Modules/EnemyStats.lua/Shared/Modules/EvolutionRules.lua/Server/Controllers/EnemyAIController.lua
のファイル構造と関数シグネチャを完全に書く。
-
B-1: TimeCycleService + WaveController の Feature Spec → Lua モジュール骨格
- Time と Wave のイベント設計を完成させて、「1 日の戦局シナリオ」をコードに固定。
-
C-1: まずは A+B を仕様として固めてから、次のラウンドで Player / Flight / UI に進む
どこから行きたい?
-
「そのまま Roblox 用 ModuleScript にする前提の関数名・引数・戻り値まで全部書いてほしいなら」
→ A-1 か B-1 どちらを先にやるかだけ指定してくれれば、その方向で一気に骨格を書きます。 -
迷うなら、こちらからは A-1(EnemyAI 状態マシンの Lua 骨格) を次で作るのを提案したい。
返答は「A-1」「B-1」「C-1」のどれでもいいし、別の切り方を出してくれてもかまわない。