Archived on 2026-10-24. The Godot rewrite is cancelled. Migration decisions and work checklists below are withdrawn. Original claims, code examples, file paths, and completion statements have not all been revalidated. Use the current documentation and issue register for maintenance decisions.
Core Game Loop¶
Purpose¶
The core loop controls a run from selected stage/characters through spawning, combat, leveling, upgrades, boss/stage progression, game over, rewards, save updates, and leaderboard submission.
Current Unity Implementation¶
Main scripts:
| Path | Script | Role |
|---|---|---|
Assets/Script/App/Core/AppInitiator.cs |
AppInitiator |
App boot, static manager initialization, data loading, services, save startup, menu load. |
Assets/Script/Shared/Session/GameSession.cs |
GameSession |
Holds selected characters, level, difficulty, player count, shop modifiers. |
Assets/Script/Game/GameSystem/Bootstrap/GameInitializer.cs |
GameInitialization |
Initializes reward tables, spawner data, players, and runtime flags. |
Assets/Script/Game/Managers/GameManager.cs |
GameManager |
Main run singleton: score, level UI, reward queue, pause/resume, game over, stage unlock, save, leaderboard. |
Assets/Script/Game/GameSystem/GameState/GameStateService.cs |
GameStateService |
Tracks paused/rewarding/game-over/boss-defeated flags and time scale. |
Assets/Script/Game/GameSystem/Player/PlayerManager.cs |
PlayerManager |
Run XP, level, level-up reward event. |
Assets/Script/Game/Stage/Timer.cs |
Timer |
Tracks game time, stage progression time, and spawn schedule time. |
Assets/Script/Game/Entities/EnemySpawner/SpawnerEventManager.cs |
SpawnerEventManager |
Spawns creep/special/boss waves from SpawnerData. |
Assets/Script/Game/GameSystem/Rewards/RewardRoller.cs |
RewardRoller |
Queues reward events, rolls upgrade cards, displays reward UI phases. |
Assets/Script/Game/GameSystem/Upgrades/UpgradeSelection.cs |
UpgradeSelection |
Player input for card selection. |
Key Data¶
GameSession.Instance.Character: selectedCharacterassets.GameSession.Instance.LevelData: selectedLevelData.GameSession.Instance.Difficulty: enum index used to chooseStageMap.GameSession.Instance.PlayerNumber: one or two players.LevelData.stageMap[difficulty]: supplies game duration, creep spawner data, special spawner data, optional dialog.GameManager.BasicRewardTable,SpecialRewardTable,UltimateRewardTable: runtime card roll pools.PlayerManager.currentExp,expToNextLevel,level: per-run progression.Timer.currentTime: stage/boss end timer.Timer.currentSpawnerTime: spawn schedule timer affected bymultiplier.Timer.currentGameTime: display/playtime timer.GameStateService:isPaused,isRewarding,isGameOver,isBossDefeated.
Runtime Flow¶
- Boot scene creates long-lived app objects.
AppInitiator.Awake()initializes input, localization, achievement/shop/collection managers, andGameDataLoader.AppInitiator.RunStartupFlow()reads Steam id if available, createsAudioServiceandSaveService, runsSaveManager.StartupAsync, loads settings, then loads main menu.- Main menu configures
GameSessionwith selected stage, difficulty, player count, characters, and shop modifiers. - Gameplay scene starts.
GameManager.Awake()creates or resets run state, initializesPlayerManager, finds components, and createsRewardRoller. GameManager.Start()asksGameInitializationto run setup, hides HUD, and pauses.GameInitialization.ImportRewardTable()filters upgrades by stage and rarity/chest rules into basic/special/ultimate reward tables.GameInitialization.PrepareSpawnAndGameManagerData()copies selected stage spawner data, end time, boss, player count, character list, and reroll count into runtime managers.GameInitialization.PreparePlayer()activates selected players, applies character weapon/stats, adds camera targets, and enables HUD status panels.GameManager.OpenGate()resumes the game, starts timers, plays gate animation, and shows HUD.- During gameplay:
Timeradvances active timers.SpawnerEventManagerchecks spawn windows and starts spawn coroutines.- Players move, target enemies, fire weapons, collect items, and take damage.
- Enemies update their state machines and drop rewards on death.
- Items grant XP, soul, chests, potions, and reward events.
- XP calls
GameManager.AddExp, thenPlayerManager.AddExperience. - If XP crosses threshold,
PlayerManager.OnRewardReadyinvokesGameManager.EnqueueReward(LevelUpReward). RewardRoller.ProcessRewardQueue()rolls cards when no reward phase is active.- Players select cards via
UpgradeSelection;UpgradeButton.SelectedUpgrade()callsUpgradeFunction.SelectUpgrade. RewardRoller.CompleteReward()clears reward state and cards.- Game over starts when both players are inactive or
Timer.currentTime >= SpawnManager.EndGameTime. GameManager.GameOver()stops timers/spawning, saves currencies/counters, fills game-over UI, pushes leaderboard data, checks achievements, saves, and pauses after UI animation.
Dependencies¶
- Heavy dependence on
GameManager.instance. GameSession.Instanceis the bridge from menu to run.GameDataLoadersupplies ScriptableObject lists and dictionary lookups.Savestatic wrapper writes currencies, unlocks, config, counters.Game.Audio,AudioResources.Instance, DOTween, and UI object references are used inside core flow.PoolManager.Instanceis used by combat, spawn, items, and feedback.
Problems / Risks¶
GameManagerowns too many unrelated responsibilities.GameStateService.SetRewarding()does not callUpdateTimeScale()directly; reward UI code checksGameManager.isPaused, so reward pause behavior may be inconsistent. This needs runtime confirmation.- Reward rolling mutates shared
Upgradeasset fields such asupgradeTakenandmodifiedWeight. GameInitializationuses boolean init flags and coroutines waiting for flags; a missing flag can stall systems.- The end condition uses
Timer.currentTime >= EndGameTime, while boss transitions stop/start timers separately. - Some logic assumes two
playerarray slots exist even whenNumberOfPlayer == 1. - UI, save, leaderboard, and gameplay run-state behavior are intertwined in game over.
Migration Notes for Godot¶
Preserve:
- Stage/character/session selection behavior.
- Three timer concepts: visible playtime, stage progress/end timer, and spawn schedule timer.
- Reward queue behavior: level-up/chest/boss rewards are queued and processed one at a time.
- One/two player reward selection rules.
- Stage unlock and achievement/save outcomes.
Redesign:
GameSessionas an autoload or explicit resource passed into the run scene.GameSessionshould be immutable enough during a run to avoid accidental asset mutation.- Split run scene into:
RunStateGameSessionStageControllerSpawnDirectorPlayerManagerRewardDirectorScoreManagerGameOverControllerUIFlowController- Use Godot signals instead of global C# events where possible.
- Keep save/leaderboard calls out of core gameplay update loops.
Open Questions¶
- Does reward selection currently pause gameplay correctly in the latest playable build?
- Does easy difficulty intentionally end at 300 seconds while other difficulties depend on boss defeat?
- Which timer should drive final score/survival achievements in Godot:
currentTimeorcurrentGameTime? - Unknown / needs manual confirmation.