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.
System Redesign Analysis¶
Summary¶
This document identifies which current Unity systems should be preserved behaviorally, redesigned structurally, split, delayed, or replaced before rebuilding the game in Godot 4.
The source evidence is the Unity analysis set under docs/migration/unity-analysis/. This file is placed one level higher, under docs/migration/, because it is not another Unity inventory page. It is a cross-system migration planning document that uses the Unity analysis as input.
The biggest migration risks are:
AbilityHolder,GameManager,UpgradeFunction,Player,PlayerWeapon,PlayerAttack, andEnemyare large or tightly coupled enough that direct translation would recreate the same architecture problems.- Runtime state is mixed into Unity ScriptableObjects, especially ability cooldowns, upgrade counts, unlock flags, and spawner flags.
- The current player setup is hardcoded around fixed player objects; the Godot architecture should support PC local co-op first, especially one or two players with keyboard/gamepad input, while staying ready for 1-4 local players and later mobile controls.
- Enemy behavior should not be reframed as one script per enemy. The current project composes enemy behavior through prefab-attached states and mechanics, and that authoring model should be preserved.
- Bosses are specialized enemies. Boss scripts such as
SAGoblinKing,SAHydra, andSAMinotaurmostly control boss-specific behavior and should remain enemy-derived in concept. - The current Unity shop should be delayed/replaced by future character-specific progression rather than migrated as-is. Old shop save values should later be refunded into soul points only.
- The reported one-minute freeze is now understood as a Unity fullscreen startup issue, not a core gameplay-system freeze. Track it as a Unity-specific open question, but do not let it drive Godot gameplay architecture.
System Redesign Table¶
| System | Current Unity Structure | Problem Level | Migration Decision | Suggested Godot Direction |
|---|---|---|---|---|
| Shared Entity model | Entity parent with Player, Enemy, and boss-enemy specializations |
Medium | Preserve behavior, redesign structure | Keep shared EntityCore concept for health/damage/death/status/feedback, then compose player/enemy/boss responsibilities around it |
| Player creation/player slots | Fixed player objects and hardcoded assumptions in GameManager, GameInitialization, PlayerManager, reward selection, camera, HUD |
Critical | Split into smaller systems | PlayerManager owns active player slots, PlayerSpawner creates players from CharacterData, PlayerInputProfile assigns keyboard/gamepad input for PC local co-op first and keeps the path open for 1-4 players/mobile later |
| Player gameplay | Player, PlayerModifier, PlayerWeapon, PlayerCollectItem, AbilityHolder, HUD references |
High | Split into smaller systems | PlayerEntity with movement, stats, health/damage, weapon, ability, collector, target sensor, and HUD adapter components |
| Enemy behavior/state composition | Enemy core plus prefab-attached EnemyBaseState, EnemyAttackState, EnemyState, EnemyMechanic scripts |
High | Preserve behavior, redesign structure | EnemyScene with EnemyStateMachine and reusable state/mechanic nodes; data defines stats/rewards, scene composition defines behavior |
| Boss behavior | Boss/enemy-derived prefabs with boss-specific scripts such as SAGoblinKing, SAHydra, SAMinotaur |
Medium | Preserve behavior, redesign structure | Bosses remain EnemyEntity variants; boss attacks become state/mechanic nodes; encounter UI/camera/music move to BossEncounterController |
| Ability system | AbilityHolder, AbilityFunction, Ability, PlayerWeapon, PlayerAttack, Player.TakeDamage |
Critical | Preserve behavior, redesign structure | AbilityData, AbilityInstance, AbilityRunner, per-ability AbilityBehavior, event-triggered activation |
| GameManager/run loop | GameManager owns run state, UI refs, rewards, game over, save/progression, leaderboard, score |
Critical | Split into smaller systems | RunState, GameSession, StageController, RewardDirector, ScoreManager, GameOverController, UIFlowController |
| Upgrade/reward effects | RewardRoller, UpgradeSelection, UpgradeFunction, UpgradeEvoFunction, WeaponEvoData |
Critical | Preserve behavior, redesign structure | UpgradeResource with effect resources, separate RewardDirector from reward UI, explicit evolution conditions |
| Stage/spawn system | LevelData, StageMap, SpawnerData, SpawnerEventManager with runtime flags in data |
High | Preserve behavior, redesign structure | Reusable gameplay scene loaded from StageData; immutable spawn schedule plus runtime SpawnDirector state |
| Combat/damage/projectile pipeline | PlayerWeapon.AttackModify, PlayerAttack, PlayerAttackCarrier, Player.TakeDamage, Enemy.TakeDamage |
High | Preserve behavior, redesign structure | Attack contexts, hit effects, damage pipeline, status/effect components, reusable projectile scenes |
| Data assets/runtime state | ScriptableObjects store static data plus runtime cooldowns, upgrade counts, unlocks, spawn flags | Critical | Preserve data, redesign ownership | Static resources only; runtime state in run/player instances; save/progression is authoritative |
| Object pooling/spawning | PoolManager dynamically registers and instantiates when pools are empty |
High | Replace with Godot-native pooled scene approach | Pool catalog, prewarm budgets, caps/metrics for high-volume enemies, projectiles, items, effects, popups |
| Items/collectibles | Items, ItemsMerger, PlayerCollectItem, enemy drops, per-item merge coroutine |
High | Preserve behavior, redesign performance path | Pooled collectibles, collector registry, magnet areas, no unbounded per-item background work |
| UI flow | MenuController, app views, GameManager HUD refs, RewardRoller UI, GameEndManager |
High | Replace with Godot-native UI structure | UIRoot, page router, HUD controller, reward UI, game-over view, signal/view-model driven updates |
| Save/progression | SaveManager, SaveService, static Save, GameDataLoader, resource unlock mutation |
High | Preserve data model, redesign authority | SaveService, ProgressionState, AchievementService, character progression service, no resource mutation as source of truth |
| Shop | ShopManager, ShopUpgrade, permanent global upgrades |
Low | Delay / replace later | Skip current shop migration; future progression should become character-specific upgrade/progression |
| Achievements | AchievementManager, GameDataCount, Achievement assets, Steam sync |
Medium | Delay until core loop works | Preserve ids/rewards later; use rule evaluator plus optional platform adapter |
| Steam/leaderboard/platform | SteamManager, SteamScript, LeaderboardManager, Steam nickname/achievements |
Medium | Delay until later phase | Platform adapter after core gameplay, save, and mobile/PC targets are stable |
| Input/local co-op/mobile controls | InputManager, keyboard/joystick mappings, hardcoded player input paths |
High | Replace with Godot-native input abstraction | Godot InputMap, player input profiles, WASD/arrow-key/gamepad local profiles first, mobile touch profile later |
| Audio/feedback | AudioService, AudioResources, AbilityResources, DamagePopUp, Announcer |
Medium | Preserve behavior, redesign routing | Audio autoload, feedback service, resource catalog, popup/announcement controller |
| Tutorial/debug/editor tools | External/Tutorial, External/Editor, cheat/editor utilities |
Unknown | Delay or remove | Exclude from first runtime migration; keep as behavior/reference material only if useful |
| Unity fullscreen startup freeze | Unity startup/fullscreen behavior, not confirmed as gameplay logic | Unknown | Do not migrate; track as Unity-specific open question | Godot startup should have explicit loading state, window defaults, and mobile-safe boot flow |
Detailed System Notes¶
Shared Entity Model¶
Current Unity Behavior¶
The current player and enemy systems share a common parent concept through Entity. This is a good conceptual foundation: both players and enemies need health, damage intake, death/disable behavior, status effects, and feedback.
Bosses are not a separate unrelated runtime category. A boss is currently an enemy specialization, with boss-specific data and attack behavior layered on top.
Related Unity Scripts¶
Assets/Script/Shared/Entity.csAssets/Script/Game/Entities/Player/Core/Player.csAssets/Script/Game/Entities/Enemies/Enemy.csAssets/Script/Game/Entities/Enemies/Boss.csAssets/Script/Game/Entities/Enemies/Boss/*.cs
Current Problems¶
- The shared parent idea is useful, but child scripts have accumulated too many responsibilities.
PlayerandEnemyboth mix core entity concerns with movement, targeting, state, reward, feedback, and ability-specific logic.- Some shared behavior is implicit through inheritance rather than explicit components or signals.
Migration Decision¶
Preserve behavior, redesign structure.
Suggested Godot Direction¶
Keep the shared entity concept, but make it composition-friendly:
EntityCore
- health
- damage intake
- death/disabled state
- status effects
- hit feedback
PlayerEntity
- owns player-specific components
EnemyEntity
- owns enemy-specific components
BossEntity
- enemy-derived variant with boss-specific state/mechanics
The important correction is not to throw away the shared parent idea. The shared concept is good; the migration should avoid recreating the large child monoliths.
Open Questions¶
- Which exact
Entityfields should be shared by all entities versus moved into player/enemy-only components?
Player Creation / Player Slots¶
Current Unity Behavior¶
The current project supports one or two players, but many systems assume fixed player arrays or specific player indexes. Player setup is driven by GameSession, GameInitialization, GameManager, selected Character assets, and scene-placed player objects.
The first target is PC local play, focused on one or two players using keyboard or gamepad. The architecture should still support 1-4 local players and later mobile controls without rewriting core systems. Online multiplayer is not part of the current architecture plan.
Related Unity Scripts¶
Assets/Script/Game/Managers/GameManager.csAssets/Script/Game/GameSystem/Bootstrap/GameInitializer.csAssets/Script/Game/GameSystem/Player/PlayerManager.csAssets/Script/Game/Entities/Player/Core/Player.csAssets/Script/Game/Entities/Player/Stats/PlayerModifier.csAssets/Script/Game/GameSystem/Upgrades/UpgradeSelection.csAssets/Script/App/Managers/InputManager.cs
Current Problems¶
- Player count is hardcoded in several gameplay/UI systems.
- Reward selection and camera behavior assume fixed player slots.
- Mobile input is a different product shape from local keyboard/controller multiplayer, but both need to fit the same player-slot model.
- If Godot starts with hardcoded one-player or two-player objects, future 3-4 player support, mobile control, or multiplayer work would require rewiring rewards, camera, input, UI, abilities, and targeting.
Migration Decision¶
Split into smaller systems.
Suggested Godot Direction¶
Use a player creation model that is PC local co-op first and 1-4 player ready:
PlayerManager
- owns active player slots
- registers/unregisters players
- exposes active_players to camera, UI, rewards, targeting, spawn logic
PlayerSpawner
- creates PlayerEntity from selected CharacterData
- applies spawn position/team/player index
- attaches selected input profile
PlayerInputProfile
- keyboard_p1 / keyboard_p2
- gamepad profiles
- mobile touch profile later without changing player creation
PlayerSlot
- player_id
- character_id
- input_profile
- ui_slot
- camera_weight/follow target
First vertical slice should spawn Soldier / Alex through the same path that can later spawn additional players. The PC path should validate WASD, arrow-key, and gamepad-ready profiles. No system should directly assume player[0] and player[1] as the complete world.
Open Questions¶
- Final mobile control and UI layout. This is intentionally not designed in the migration docs yet.
Player Gameplay¶
Current Unity Behavior¶
Player controls character setup, movement, target list, resources, damage/shields/death, regen, effects, and some feedback. PlayerModifier calculates final stats. PlayerWeapon aims, reloads, fires, and applies many ability-specific attack changes. PlayerCollectItem handles magnet/collectible behavior.
Related Unity Scripts¶
Assets/Script/Game/Entities/Player/Core/Player.csAssets/Script/Game/Entities/Player/Stats/PlayerModifier.csAssets/Script/Game/Entities/Player/Weapons/PlayerWeapon.csAssets/Script/Game/Entities/Player/Collectibles/PlayerCollectItem.csAssets/Script/Game/Entities/Player/Presentation/StatusPanel.csAssets/Script/Game/Entities/Player/Core/AbilityHolder.csAssets/Script/Shared/ScriptableObjects/Character.cs
Current Problems¶
Playeris too broad.- Damage handling contains many ability-specific branches.
- Stats recalculate too often and depend on direct ability checks.
- Target sorting happens every frame and can grow expensive.
- Collection checks can become expensive with many items and multiple players.
Migration Decision¶
Split into smaller systems.
Suggested Godot Direction¶
Use PlayerEntity as a coordinating scene with small components:
PlayerEntity
- PlayerMovement
- PlayerStats
- PlayerHealth
- PlayerWeaponController
- PlayerAbilityRunner
- PlayerTargetSensor
- PlayerCollector
- PlayerHUDAdapter
Preserve character stats, stamina/dash feel, target-priority behavior, item pickup behavior, and survivability rules, but move ability branches out of Player.TakeDamage.
Open Questions¶
- Which stat formulas must match Unity exactly for balance?
- Should target priority match Unity hitpoint sorting exactly or only behaviorally?
Enemy Behavior / State Composition¶
Current Unity Behavior¶
Current enemies are not implemented as one script per enemy type. The project uses a shared Enemy core and then builds behavior by attaching state and mechanic scripts to enemy prefabs. This includes base states, attack states, enemy state scripts, enemy mechanic scripts, and boss attack scripts.
This authoring model is worth preserving.
Related Unity Scripts¶
Assets/Script/Game/Entities/Enemies/Enemy.csAssets/Script/Game/Entities/Enemies/EnemyCore/EnemyBaseState.csAssets/Script/Game/Entities/Enemies/EnemyCore/EnemyAttackState.csAssets/Script/Game/Entities/Enemies/EnemyCore/EnemyAttack.csAssets/Script/Game/Entities/Enemies/EnemyCore/EnemyMechanic.csAssets/Script/Game/Entities/Enemies/EnemyState/*.csAssets/Script/Game/Entities/Enemies/Mechanic/*.cs
Current Problems¶
Enemystill mixes health, target finding, state machine control, damage, rewards, death, crowd control, and flee logic.- Some targeting/search behavior uses scene-wide searches.
- Runtime behavior depends on prefab wiring, so the migration must inspect scenes/prefabs, not just scripts.
- Large enemy waves can stress damage popups, item drops, pooling, and per-enemy updates.
Migration Decision¶
Preserve behavior, redesign structure.
Suggested Godot Direction¶
Keep prefab/scene composition as the authoring model:
EnemyScene
- EnemyEntity
- EnemyStateMachine
- State: Chase / Idle / Stroll / Flee
- AttackState: Melee / Ranged / Mortar / Charge / Summon
- EnemyMechanic nodes
- EnemyRewardDropper
- EnemyCrowdControl
Enemy data should define stats, rewards, type, resistances, and ids. Enemy scenes should define behavior by composed state/mechanic nodes.
Do not migrate into one script per enemy. Also do not copy the large Enemy.cs unchanged.
Open Questions¶
- Which prefab-attached state/mechanic combinations are production for each enemy?
- Are all UnityEvent links represented in source-controlled prefabs?
Boss Behavior¶
Current Unity Behavior¶
Bosses are enemy specializations. Boss scripts such as SAGoblinKing, SAHydra, and SAMinotaur mostly control how each boss behaves, especially special attacks and boss-specific phases or patterns.
Boss transition behavior is partly in the spawn/stage manager, not only inside boss scripts.
Related Unity Scripts¶
Assets/Script/Game/Entities/Enemies/Boss.csAssets/Script/Game/Entities/Enemies/Boss/SAGoblinKing.csAssets/Script/Game/Entities/Enemies/Boss/SAHydra.csAssets/Script/Game/Entities/Enemies/Boss/SAMinotaur.csAssets/Script/Game/Entities/EnemySpawner/SpawnerEventManager.csAssets/Script/Game/Entities/Enemies/EnemyState/*.cs
Current Problems¶
- Boss-specific behavior, enemy behavior, spawn transition, camera lock, music, UI health bar, and enemy cleanup are coupled across boss scripts and
SpawnerEventManager. - The boss scripts should remain behavior-specific, but encounter orchestration should not live inside the boss entity.
Migration Decision¶
Preserve behavior, redesign structure.
Suggested Godot Direction¶
Bosses should remain enemy-derived:
BossEntity : EnemyEntity
- BossStateMachine
- Boss special attack states/mechanics
- Boss phase data
BossEncounterController
- starts encounter
- locks/unlocks camera
- switches music
- owns boss health UI link
- clears or redirects current enemies
- ends encounter
Boss attack scripts should become boss-specific state/mechanic nodes under the boss scene. Boss encounter presentation should be separate.
Open Questions¶
- Which boss attacks are driven by boss scripts versus prefab-wired state scripts?
- Should boss phase thresholds be data-driven from the start?
Ability System¶
Current Unity Behavior¶
The current ability system uses Ability ScriptableObjects for ids/cooldowns/stamina, but most behavior is centralized in AbilityHolder and spread through PlayerWeapon, PlayerAttack, and Player.TakeDamage.
Related Unity Scripts¶
Assets/Script/Game/Entities/Player/Core/AbilityHolder.csAssets/Script/Game/Utilities/AbilityFunction.csAssets/Script/Shared/ScriptableObjects/Ability.csAssets/Script/Game/Entities/Player/Weapons/PlayerWeapon.csAssets/Script/Game/Entities/Player/Combat/PlayerAttack.csAssets/Script/Game/Entities/Player/Combat/PlayerAttackCarrier.cs
Current Problems¶
AbilityHolderknows too much about every ability.- Ability cooldown state is stored on shared data assets.
- Ability behavior is split unpredictably across multiple large scripts.
- Passive and event-based abilities are often polled or checked in hot paths.
- Some abilities are incomplete or unclear.
Migration Decision¶
Preserve behavior, redesign structure.
Suggested Godot Direction¶
Use modular ability ownership:
AbilityData
- id, name, icon, cooldown, stamina, tags, base scaling
AbilityInstance
- owner, level, cooldown, stacks, active state
AbilityRunner
- owns active abilities
- receives events: on_dash, on_fire, on_hit, on_damage_taken, on_timer
- requests behavior activation
AbilityBehavior
- one script/scene per complex ability or reusable behavior family
Preserve character play patterns, cooldowns, stamina costs, triggers, and visible effects, but do not copy the old holder.
Open Questions¶
- Which abilities are production versus testing/in-development?
- Are Unity ability assets shared between players at runtime?
GameManager / Run Loop¶
Current Unity Behavior¶
GameManager is the central gameplay singleton. It coordinates run state, UI references, players, rewards, score, game over, save/progression, stage unlocks, leaderboard payloads, and damage popup caps.
Related Unity Scripts¶
Assets/Script/Game/Managers/GameManager.csAssets/Script/Game/GameSystem/Bootstrap/GameInitializer.csAssets/Script/Game/GameSystem/GameState/GameStateService.csAssets/Script/Game/Stage/Timer.csAssets/Script/Game/GameSystem/Rewards/RewardRoller.csAssets/Script/Game/Managers/GameEndManager.cs
Current Problems¶
- Too many unrelated responsibilities.
- Core gameplay state stores UI references.
- Game over mixes save, achievements, leaderboard, UI, audio, enemy behavior, and pause state.
- Many scripts depend on
GameManager.instance.
Migration Decision¶
Split into smaller systems.
Suggested Godot Direction¶
Use small run coordinators:
GameSession
RunState
StageController
SpawnDirector
PlayerManager
RewardDirector
ScoreManager
GameOverController
UIFlowController
FeedbackController
RunState should own pause/reward/game-over flags. UI should observe state rather than being stored inside the run authority.
Open Questions¶
- Which game-over summary fields must match Unity exactly?
- Exact state split between reward pause and pause-menu pause, so reward selection cannot soft-lock.
Upgrade / Reward Effects¶
Current Unity Behavior¶
RewardRoller rolls reward choices and also handles reward UI/animation. UpgradeFunction applies all upgrade effects through a large switch. Evolution is hardcoded by ability type in UpgradeEvoFunction, and weapon evolution is editor-wired through WeaponEvoData.
Related Unity Scripts¶
Assets/Script/Game/GameSystem/Rewards/RewardRoller.csAssets/Script/Game/GameSystem/Upgrades/UpgradeFunction.csAssets/Script/Game/GameSystem/Upgrades/UpgradeSelection.csAssets/Script/Game/GameSystem/Upgrades/UpgradeEvoFunction.csAssets/Script/Game/GameSystem/Upgrades/WeaponEvoData.csAssets/Script/Shared/ScriptableObjects/Upgrade.cs
Current Problems¶
UpgradeFunctionis a large hardcoded switch.- Upgrade data uses parallel arrays for effect ids and values.
- Runtime state such as
upgradeTakenandmodifiedWeightis stored on assets. - Reward logic and reward UI are coupled.
- Some upgrade enum entries appear unfinished or unclear.
Migration Decision¶
Preserve behavior, redesign structure.
Suggested Godot Direction¶
Use upgrade resources with effect objects:
UpgradeResource
- id
- rarity
- requirements
- roll weight
- effects
UpgradeEffect
- apply(context)
RewardDirector
- queue and roll logic
RewardUI
- display and selection only
Evolution conditions should become explicit condition resources or scripts.
Open Questions¶
- Which upgrade ids are authoritative:
idname, localized name, or asset name? - Which unfinished upgrades should be excluded?
Stage / Spawn System¶
Current Unity Behavior¶
Stages use LevelData and StageMap assets with durations, boss refs, music, and spawner data. SpawnerEventManager runs creep waves, special waves, miniboss suppression, boss transitions, and stage state.
Related Unity Scripts¶
Assets/Script/Shared/ScriptableObjects/LevelData.csAssets/Script/Game/Entities/EnemySpawner/SpawnerData.csAssets/Script/Game/Entities/EnemySpawner/SpawnerEventManager.csAssets/Script/Game/Stage/Timer.cs
Current Problems¶
- Spawn data assets contain runtime flags such as
isSpawningandisActive. - Stage and spawn runtime state are mixed.
- Special/miniboss suppression depends on timer/id matching and can pause creep waves.
- Boss transition changes camera, music, enemy behavior, UI, and timers in one flow.
Migration Decision¶
Preserve behavior, redesign structure.
Suggested Godot Direction¶
Use one reusable gameplay scene loaded by stage data:
GameScene
- StageController
- SpawnDirector
- PlayerManager
- BossEncounterController
StageData
- background
- music
- duration
- boss data
- spawn schedules
- environmental settings
SpawnSchedule
- immutable wave data
SpawnRuntimeState
- active/spawning flags outside resource data
Open Questions¶
- Regular Stage 1, Stage 2, and Stage 3 are the production migration sources. Do not use
Stage 1 neworStage 3 ZhangYG. - Which stage-specific mechanics are real versus placeholder?
Combat / Damage / Projectile Pipeline¶
Current Unity Behavior¶
Weapon firing, projectile setup, hit effects, status effects, damage calculation, shield effects, and enemy damage response are spread across PlayerWeapon, PlayerAttack, PlayerAttackCarrier, Player.TakeDamage, and Enemy.TakeDamage.
Related Unity Scripts¶
Assets/Script/Game/Entities/Player/Weapons/PlayerWeapon.csAssets/Script/Game/Entities/Player/Combat/PlayerAttack.csAssets/Script/Game/Entities/Player/Combat/PlayerAttackCarrier.csAssets/Script/Game/Entities/Player/Core/Player.csAssets/Script/Game/Entities/Enemies/Enemy.cs
Current Problems¶
- Many effect flags are copied onto one projectile class.
- Damage order is important but hidden in large methods.
- Player damage contains many ability-specific branches.
- Projectile modifiers can multiply spawned objects and pool pressure.
Migration Decision¶
Preserve behavior, redesign structure.
Suggested Godot Direction¶
Create an explicit combat context model:
AttackContext
- owner
- base damage
- crit result
- tags/effects
- source ability/weapon
HitEffect
- poison, freeze, ricochet, explosion, vampiric, hydra split
DamagePipeline
- shield/block/reduction/final damage/death order
Preserve player-facing damage order, but make effects modular.
Open Questions¶
- Which damage/shield order must be exact for balance?
- Which projectile combinations are valid in production?
Data Assets / Runtime State¶
Current Unity Behavior¶
Unity ScriptableObjects store useful static data, but they also store runtime state: ability cooldowns, upgrade counts, modified weights, unlock flags, shop levels, stage unlocks, and spawner active flags.
Related Unity Scripts¶
Assets/Script/Shared/ScriptableObjects/Ability.csAssets/Script/Shared/ScriptableObjects/Upgrade.csAssets/Script/Shared/ScriptableObjects/Character.csAssets/Script/Shared/ScriptableObjects/LevelData.csAssets/Script/Game/Entities/EnemySpawner/SpawnerData.csAssets/Script/Shared/ScriptableObjects/Achievement.csAssets/Script/Shared/ScriptableObjects/ShopUpgrade.cs
Current Problems¶
- Data and runtime state can leak between runs or players.
- Play-mode/editor serialization can dirty assets.
- Save state and asset unlock fields overlap.
Migration Decision¶
Preserve data, redesign ownership.
Suggested Godot Direction¶
Use resource data as static definitions only:
Static Resources
- CharacterData
- AbilityData
- UpgradeData
- StageData
- EnemyData
- AchievementData
Runtime State
- AbilityInstance
- UpgradeRunState
- SpawnRuntimeState
- PlayerRuntimeState
Save State
- progression/unlocks/currencies/counters
Open Questions¶
- Existing Unity saves must be imported later; exact
.datand.jsonschema still needs confirmation. - Which ids are final and stable, and which saved fields still use names instead of ids?
Object Pooling / Spawning¶
Current Unity Behavior¶
PoolManager dynamically registers pools and instantiates more objects when a queue is empty. Many systems spawn enemies, projectiles, effects, drops, damage popups, and companion attacks.
Related Unity Scripts¶
Assets/Script/Game/Managers/PoolManager.csAssets/Script/Game/Entities/EnemySpawner/SpawnerEventManager.csAssets/Script/Game/Entities/Player/Weapons/PlayerWeapon.csAssets/Script/Game/Entities/Player/Combat/PlayerAttack.csAssets/Script/Game/Entities/Enemies/Enemy.csAssets/Script/Game/Items/Items.cs
Current Problems¶
- No clear prewarm/cap policy.
- Cold pool bursts can instantiate during combat.
- Damage popups and item drops can create pressure.
- Some direct
Instantiatepaths remain.
Migration Decision¶
Replace with Godot-native pooled scene approach.
Suggested Godot Direction¶
Use a pool/spawn catalog:
SpawnCatalog
- scene id to PackedScene
- pool budget
- prewarm count
- max active count
PoolService
- acquire(scene_id)
- release(node)
- metrics/debug counters
High-volume objects should have explicit budgets.
Open Questions¶
- Which prefabs need prewarm budgets first?
- Should damage popups be capped globally or per screen?
Items / Collectibles¶
Current Unity Behavior¶
Enemies drop rewards as pooled Items. Players maintain collectible lists and check magnet radius. Items can run merge-check coroutines that periodically spawn merger objects.
Related Unity Scripts¶
Assets/Script/Game/Items/Items.csAssets/Script/Game/Items/ItemsMerger.csAssets/Script/Game/Items/ItemsBreakable.csAssets/Script/Game/Entities/Player/Collectibles/PlayerCollectItem.csAssets/Script/Game/Entities/Enemies/Enemy.cs
Current Problems¶
- Per-item background loops can accumulate.
- Collector checks can become expensive with many items and multiple players.
- Drops affect pool pressure.
Migration Decision¶
Preserve behavior, redesign performance path.
Suggested Godot Direction¶
Use collectible areas and registries:
Collectible
- item type
- value
- collect behavior
CollectibleRegistry
- active items
PlayerCollector
- magnet area
- picks nearest/overlapping collectibles
Avoid unbounded per-item polling/coroutine patterns.
Open Questions¶
- Which item merge behavior is required in the first Godot build?
UI Flow¶
Current Unity Behavior¶
App UI, gameplay HUD, rewards, pause/settings, and game-over UI are spread through menu controllers, views, GameManager, RewardRoller, UpgradeSelection, and GameEndManager.
Related Unity Scripts¶
Assets/Script/App/UI/Controllers/MenuController.csAssets/Script/App/UI/Shared/Page.csAssets/Script/App/UI/Views/*.csAssets/Script/Game/GameSystem/Rewards/RewardRoller.csAssets/Script/Game/GameSystem/Upgrades/UpgradeSelection.csAssets/Script/Game/Managers/GameEndManager.csAssets/Script/Game/Entities/Player/Presentation/StatusPanel.cs
Current Problems¶
- Gameplay UI references live in core gameplay managers.
- Reward roll logic and UI animation are coupled.
- HUD polls player stats rather than observing changes.
- Game-over UI is built inside game-over gameplay flow.
Migration Decision¶
Replace with Godot-native UI structure.
Suggested Godot Direction¶
Use UI controllers that observe game state:
UIRoot
PageRouter
HUDController
RewardUIController
PauseMenuController
GameOverView
FeedbackLayer
Reward UI should emit selections; it should not apply upgrades directly.
Open Questions¶
- Which UI screens are needed before the first playable mobile slice?
Save / Progression¶
Current Unity Behavior¶
Save/progression uses SaveManager, SaveService, static Save, GameDataLoader, achievements, shop, counters, and ScriptableObject unlock mutation.
Related Unity Scripts¶
Assets/Script/App/Core/SaveManager.csAssets/Script/TinyChaos/Services/Save/SaveService.csAssets/Script/App/Data/Save.csAssets/Script/Game/Resources/GameDataLoader.csAssets/Script/Shared/GameDataCount.csAssets/Script/App/Managers/AchievementManager.csAssets/Script/App/Managers/ShopManager.cs
Current Problems¶
- Save dictionaries and asset fields both represent progression.
- Static save facade is globally coupled.
- Steam nickname/achievements are mixed into general progression.
- Current shop progression will be replaced.
Migration Decision¶
Preserve data model, redesign authority.
Suggested Godot Direction¶
Use save/progression services:
SaveService
ProgressionState
AchievementService
CharacterProgressionService
PlatformAdapter
The save state should be the source of truth. Resources should not be mutated as progression authority.
Existing Unity save/config data must be migrated later. Current known source formats are .dat player data and .json config, with a future target of encrypted JSON. Because ids are mostly manually typed, save migration needs a final id/alias audit before conversion.
Open Questions¶
- Exact legacy
.datand.jsonschema fixtures. - Which saved values use ids versus names beyond the already known special-upgrade
upgradeNamecase. - Final id normalization rules before conversion.
Shop¶
Current Unity Behavior¶
The current Unity shop provides permanent global upgrades through ShopManager and ShopUpgrade assets. These values are applied to run modifiers through GameSession.
Related Unity Scripts¶
Assets/Script/App/Managers/ShopManager.csAssets/Script/Shared/ScriptableObjects/ShopUpgrade.csAssets/Script/App/UI/Views/ShopView.csAssets/Script/App/UI/Buttons/ShopButton.cs
Current Problems¶
- The future design is not the same system. Current shop upgrades are planned to be remade into character-specific upgrades/progression.
- Migrating the existing shop as-is would add work to a system that will be replaced.
Migration Decision¶
Delay until later phase / replace later.
Suggested Godot Direction¶
Skip current shop in the first vertical slice. Do not migrate the current shop UI or permanent-global-upgrade architecture as-is. Preserve old shop ids/levels for save conversion only so they can refund into soul points.
Open Questions¶
- Final character-specific progression design that replaces the shop.
Achievements¶
Current Unity Behavior¶
Achievements are driven by GameDataCount, AchievementManager, achievement assets, save dictionaries, rewards, popups, and Steam sync.
Related Unity Scripts¶
Assets/Script/App/Managers/AchievementManager.csAssets/Script/Shared/GameDataCount.csAssets/Script/Shared/ScriptableObjects/Achievement.csAssets/Script/Game/Events/GameEvents.cs
Current Problems¶
- Tied to static events/save/platform behavior.
- Not required for the first gameplay proof.
- Achievement rewards can affect unlocks, so ids should be preserved.
Migration Decision¶
Delay until core loop works.
Suggested Godot Direction¶
Preserve achievement ids and rewards for later. Rebuild as an AchievementService that consumes run/progression events and optionally syncs through a platform adapter.
Open Questions¶
- Which achievements unlock production abilities/upgrades?
Steam / Leaderboard / Platform¶
Current Unity Behavior¶
Steam and leaderboard logic is integrated into save identity, achievements, game-over leaderboard payloads, menu UI, and HTTP/local cache behavior.
Related Unity Scripts¶
Assets/Script/External/Steamworks.NET/*Assets/Script/External/Network/LeaderboardManager.csAssets/Script/App/UI/Views/LeaderboardView.csAssets/Script/App/UI/Controllers/LeaderboardUIController.csAssets/Script/App/Data/Save.cs
Current Problems¶
- Platform-specific code should not block core gameplay migration.
- Mobile target may not use Steam.
- Leaderboard payload depends on abilities/upgrades ids that should stabilize first.
Migration Decision¶
Delay until later phase.
Suggested Godot Direction¶
Use a platform adapter and leaderboard service after the core gameplay loop and save/progression ids are stable.
Open Questions¶
- Is Steam required for PC launch, and is mobile leaderboard required?
Input / Local Co-Op / Mobile Controls¶
Current Unity Behavior¶
InputManager handles keyboard/joystick mappings and input images. Gameplay reads input in several player/ability/UI scripts. The current concept is hardcoded around existing local player slots.
Related Unity Scripts¶
Assets/Script/App/Managers/InputManager.csAssets/Script/Game/Entities/Player/Core/Player.csAssets/Script/Game/Entities/Player/Core/AbilityHolder.csAssets/Script/Game/GameSystem/Upgrades/UpgradeSelection.cs
Current Problems¶
- PC local co-op is the first primary path.
- Future 3-4 local player support and mobile controls need input profiles, not hardcoded player indexes.
- UI navigation and gameplay input are mixed in several systems.
Migration Decision¶
Replace with Godot-native input abstraction.
Suggested Godot Direction¶
Use Godot InputMap plus explicit player profiles:
PlayerInputProfile
- keyboard_p1
- keyboard_p2
- controller_slot_n
- mobile_touch_later
InputRouter
- maps profile events to player actions
- separates gameplay actions from UI actions
First slice should support PC keyboard local profiles and gamepad-ready routing. Do not define the final mobile layout in this document.
Open Questions¶
- Final mobile control and UI layout.
- Final mobile control layout.
Audio / Feedback¶
Current Unity Behavior¶
Audio and feedback use AudioService, AudioResources, AbilityResources, UIResourceProvider, damage popups, announcer, entity blink, and pooled VFX.
Related Unity Scripts¶
Assets/Script/TinyChaos/Services/Audio/AudioService.csAssets/Script/Game/Resources/AudioResources.csAssets/Script/Game/Resources/AbilityResources.csAssets/Script/Game/Stage/DamagePopUp.csAssets/Script/Game/Utilities/Announcer.csAssets/Script/Shared/Entity.cs
Current Problems¶
- Direct global clip/prefab references are spread through gameplay.
- Damage popup limiting happens after spawn.
- Feedback is embedded in gameplay methods.
Migration Decision¶
Preserve behavior, redesign routing.
Suggested Godot Direction¶
Use:
AudioService
FeedbackService
ResourceCatalog
DamagePopupController
AnnouncerController
Preserve audio categories, anti-stacking, popup colors, and major feedback timing.
Open Questions¶
- Which feedback effects are required for the first slice?
Tutorial / Debug / Editor Tools¶
Current Unity Behavior¶
Tutorial scripts appear separate from core gameplay. Editor tools and cheat windows support development but are not runtime game systems.
Related Unity Scripts¶
Assets/Script/External/Tutorial/*Assets/Script/External/Editor/*
Current Problems¶
- Tutorial behavior may duplicate gameplay logic.
- Editor tools are Unity-specific.
- Neither is necessary for the first Godot vertical slice.
Migration Decision¶
Delay or remove.
Suggested Godot Direction¶
Do not migrate these into runtime initially. Keep them as references only. Rebuild tutorial later using final gameplay systems if needed.
Open Questions¶
- Should the tutorial be ported, redesigned, or skipped?
Unity Fullscreen Startup Freeze¶
Current Unity Behavior¶
The previously reported one-minute freeze/stuck issue is now understood as a startup issue when opening the Unity game in fullscreen mode. It is not currently described as an in-run spawn/reward/gameplay stall.
Related Unity Scripts¶
Assets/Script/App/Core/AppInitiator.csAssets/Script/App/Core/SplashUIController.csAssets/Script/App/Managers/GameSettings.csAssets/Script/App/UI/Views/MenuView.cs- Unity window/fullscreen settings outside scripts may also be involved.
Current Problems¶
- The exact fullscreen startup cause is Unknown / needs manual confirmation.
- It may be Unity/window/display/startup-specific and may disappear in Godot.
- Treating it as a gameplay architecture problem would mis-prioritize migration work.
Migration Decision¶
Do not migrate; track as Unity-specific open question.
Suggested Godot Direction¶
Use explicit boot/loading flow and safe window/mobile defaults:
BootScene
- initialize settings
- show loading state
- apply window/mobile defaults
- load main menu or game scene
Do not design gameplay systems around this Unity-specific freeze unless a Godot reproduction exists.
Open Questions¶
- Which fullscreen mode, monitor setup, and build target reproduce the Unity startup freeze?
- Does the issue involve settings load, display mode switching, save load, or Steam initialization?
Recommended Redesign Priorities¶
Must Redesign Before Implementation¶
- Ability system: do not copy
AbilityHolderor cooldown state on data assets. - GameManager/run loop: split the singleton into run state, stage, reward, score, game-over, UI, save/progression, and platform boundaries.
- Player creation/player slots: build PC local co-op first, but keep systems 1-4 local player and mobile-control ready.
- Player damage/combat pipeline: move ability branches out of
Player.TakeDamage,PlayerWeapon.AttackModify, andPlayerAttack. - Data asset runtime ownership: resources must be static definitions, not runtime state.
- Stage/spawn runtime state: keep spawn schedules immutable and move active flags to runtime objects.
- Reward UI/controller boundary: separate reward rolling/applying from UI display/selection.
- Object pooling/high-volume spawning: define prewarm, caps, and metrics before implementing projectile/enemy/item-heavy systems.
Can Rebuild After Vertical Slice¶
- Steam/platform integration.
- Leaderboard posting and leaderboard UI.
- Full achievement UI and platform achievement sync.
- Character-specific progression replacing the current shop.
- Tutorial.
- Collection/database screens.
- Debug/editor tools.
- Full localization polish beyond keys needed by the first slice.
- Full 3-4 player UI.
- Final mobile control UI.
Can Preserve Behaviorally¶
- Shared
Entityconcept for health, damage, death, status, and feedback. - Enemy prefab/state composition authoring model.
- Bosses as specialized enemies with boss-specific behavior controllers.
- Character ids, base stats, starting weapons, and default ability identities.
- Stage durations, wave timings, and boss transition behavior after spawn runtime state is cleaned up.
- XP/level-up reward concept.
- Upgrade ids, rarity/weight behavior, requirements, and evolution conditions.
- Achievement ids/rewards, when achievements are rebuilt later.
- Audio categories, anti-stacking behavior, damage popup colors, and announcer timing.
Open Questions for Manual Review¶
- Full behavior validation for production abilities/upgrades from
Assets/Resources. - Exact Unity save/config fixtures and conversion path to encrypted JSON.
- Final id/alias map, including the known special-upgrade
upgradeNamesave usage. - Exact Steam/leaderboard implementation details for PC after the core loop is stable, and later Stove/PlayStore service requirements if mobile publishing happens.
- Exact reproduction path of the Unity fullscreen startup freeze.
- Whether Celestial and Priestess force-unlocked values are intentional.
- Which UnityEvent weapon evolution hooks are wired for each character.
- Final character-specific progression design replacing the old shop.
Recommended First Godot Vertical Slice¶
- One reusable gameplay scene.
- Soldier / Alex spawned through
PlayerManagerandPlayerSpawner. - PC local input path for WASD, arrow-key, and gamepad-ready profiles.
- One
EntityCoreshared by player and enemy. - Stage 1 data, exact Unity numbers, and Stage 1 enemies using the new enemy state composition pattern.
- Stage 1 boss if the slice targets the whole Stage 1 loop.
- One basic weapon, one projectile, one damage path, one XP pickup.
- One level-up reward with a basic stat upgrade.
- One ability implemented through the redesigned ability runner.
- Basic HUD, pause, and game-over state.
- UI text uses localization keys from the start.
- No shop UI, Steam, leaderboard, tutorial, full achievement UI, final mobile controls, or full 4-player UI yet.