Skip to content

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, and Enemy are 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, and SAMinotaur mostly 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.

  • Assets/Script/Shared/Entity.cs
  • Assets/Script/Game/Entities/Player/Core/Player.cs
  • Assets/Script/Game/Entities/Enemies/Enemy.cs
  • Assets/Script/Game/Entities/Enemies/Boss.cs
  • Assets/Script/Game/Entities/Enemies/Boss/*.cs

Current Problems

  • The shared parent idea is useful, but child scripts have accumulated too many responsibilities.
  • Player and Enemy both 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 Entity fields 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.

  • Assets/Script/Game/Managers/GameManager.cs
  • Assets/Script/Game/GameSystem/Bootstrap/GameInitializer.cs
  • Assets/Script/Game/GameSystem/Player/PlayerManager.cs
  • Assets/Script/Game/Entities/Player/Core/Player.cs
  • Assets/Script/Game/Entities/Player/Stats/PlayerModifier.cs
  • Assets/Script/Game/GameSystem/Upgrades/UpgradeSelection.cs
  • Assets/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.

  • Assets/Script/Game/Entities/Player/Core/Player.cs
  • Assets/Script/Game/Entities/Player/Stats/PlayerModifier.cs
  • Assets/Script/Game/Entities/Player/Weapons/PlayerWeapon.cs
  • Assets/Script/Game/Entities/Player/Collectibles/PlayerCollectItem.cs
  • Assets/Script/Game/Entities/Player/Presentation/StatusPanel.cs
  • Assets/Script/Game/Entities/Player/Core/AbilityHolder.cs
  • Assets/Script/Shared/ScriptableObjects/Character.cs

Current Problems

  • Player is 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.

  • Assets/Script/Game/Entities/Enemies/Enemy.cs
  • Assets/Script/Game/Entities/Enemies/EnemyCore/EnemyBaseState.cs
  • Assets/Script/Game/Entities/Enemies/EnemyCore/EnemyAttackState.cs
  • Assets/Script/Game/Entities/Enemies/EnemyCore/EnemyAttack.cs
  • Assets/Script/Game/Entities/Enemies/EnemyCore/EnemyMechanic.cs
  • Assets/Script/Game/Entities/Enemies/EnemyState/*.cs
  • Assets/Script/Game/Entities/Enemies/Mechanic/*.cs

Current Problems

  • Enemy still 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.

  • Assets/Script/Game/Entities/Enemies/Boss.cs
  • Assets/Script/Game/Entities/Enemies/Boss/SAGoblinKing.cs
  • Assets/Script/Game/Entities/Enemies/Boss/SAHydra.cs
  • Assets/Script/Game/Entities/Enemies/Boss/SAMinotaur.cs
  • Assets/Script/Game/Entities/EnemySpawner/SpawnerEventManager.cs
  • Assets/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.

  • Assets/Script/Game/Entities/Player/Core/AbilityHolder.cs
  • Assets/Script/Game/Utilities/AbilityFunction.cs
  • Assets/Script/Shared/ScriptableObjects/Ability.cs
  • Assets/Script/Game/Entities/Player/Weapons/PlayerWeapon.cs
  • Assets/Script/Game/Entities/Player/Combat/PlayerAttack.cs
  • Assets/Script/Game/Entities/Player/Combat/PlayerAttackCarrier.cs

Current Problems

  • AbilityHolder knows 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.

  • Assets/Script/Game/Managers/GameManager.cs
  • Assets/Script/Game/GameSystem/Bootstrap/GameInitializer.cs
  • Assets/Script/Game/GameSystem/GameState/GameStateService.cs
  • Assets/Script/Game/Stage/Timer.cs
  • Assets/Script/Game/GameSystem/Rewards/RewardRoller.cs
  • Assets/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.

  • Assets/Script/Game/GameSystem/Rewards/RewardRoller.cs
  • Assets/Script/Game/GameSystem/Upgrades/UpgradeFunction.cs
  • Assets/Script/Game/GameSystem/Upgrades/UpgradeSelection.cs
  • Assets/Script/Game/GameSystem/Upgrades/UpgradeEvoFunction.cs
  • Assets/Script/Game/GameSystem/Upgrades/WeaponEvoData.cs
  • Assets/Script/Shared/ScriptableObjects/Upgrade.cs

Current Problems

  • UpgradeFunction is a large hardcoded switch.
  • Upgrade data uses parallel arrays for effect ids and values.
  • Runtime state such as upgradeTaken and modifiedWeight is 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.

  • Assets/Script/Shared/ScriptableObjects/LevelData.cs
  • Assets/Script/Game/Entities/EnemySpawner/SpawnerData.cs
  • Assets/Script/Game/Entities/EnemySpawner/SpawnerEventManager.cs
  • Assets/Script/Game/Stage/Timer.cs

Current Problems

  • Spawn data assets contain runtime flags such as isSpawning and isActive.
  • 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 new or Stage 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.

  • Assets/Script/Game/Entities/Player/Weapons/PlayerWeapon.cs
  • Assets/Script/Game/Entities/Player/Combat/PlayerAttack.cs
  • Assets/Script/Game/Entities/Player/Combat/PlayerAttackCarrier.cs
  • Assets/Script/Game/Entities/Player/Core/Player.cs
  • Assets/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.

  • Assets/Script/Shared/ScriptableObjects/Ability.cs
  • Assets/Script/Shared/ScriptableObjects/Upgrade.cs
  • Assets/Script/Shared/ScriptableObjects/Character.cs
  • Assets/Script/Shared/ScriptableObjects/LevelData.cs
  • Assets/Script/Game/Entities/EnemySpawner/SpawnerData.cs
  • Assets/Script/Shared/ScriptableObjects/Achievement.cs
  • Assets/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 .dat and .json schema 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.

  • Assets/Script/Game/Managers/PoolManager.cs
  • Assets/Script/Game/Entities/EnemySpawner/SpawnerEventManager.cs
  • Assets/Script/Game/Entities/Player/Weapons/PlayerWeapon.cs
  • Assets/Script/Game/Entities/Player/Combat/PlayerAttack.cs
  • Assets/Script/Game/Entities/Enemies/Enemy.cs
  • Assets/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 Instantiate paths 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.

  • Assets/Script/Game/Items/Items.cs
  • Assets/Script/Game/Items/ItemsMerger.cs
  • Assets/Script/Game/Items/ItemsBreakable.cs
  • Assets/Script/Game/Entities/Player/Collectibles/PlayerCollectItem.cs
  • Assets/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.

  • Assets/Script/App/UI/Controllers/MenuController.cs
  • Assets/Script/App/UI/Shared/Page.cs
  • Assets/Script/App/UI/Views/*.cs
  • Assets/Script/Game/GameSystem/Rewards/RewardRoller.cs
  • Assets/Script/Game/GameSystem/Upgrades/UpgradeSelection.cs
  • Assets/Script/Game/Managers/GameEndManager.cs
  • Assets/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.

  • Assets/Script/App/Core/SaveManager.cs
  • Assets/Script/TinyChaos/Services/Save/SaveService.cs
  • Assets/Script/App/Data/Save.cs
  • Assets/Script/Game/Resources/GameDataLoader.cs
  • Assets/Script/Shared/GameDataCount.cs
  • Assets/Script/App/Managers/AchievementManager.cs
  • Assets/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 .dat and .json schema fixtures.
  • Which saved values use ids versus names beyond the already known special-upgrade upgradeName case.
  • 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.

  • Assets/Script/App/Managers/ShopManager.cs
  • Assets/Script/Shared/ScriptableObjects/ShopUpgrade.cs
  • Assets/Script/App/UI/Views/ShopView.cs
  • Assets/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.

  • Assets/Script/App/Managers/AchievementManager.cs
  • Assets/Script/Shared/GameDataCount.cs
  • Assets/Script/Shared/ScriptableObjects/Achievement.cs
  • Assets/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.

  • Assets/Script/External/Steamworks.NET/*
  • Assets/Script/External/Network/LeaderboardManager.cs
  • Assets/Script/App/UI/Views/LeaderboardView.cs
  • Assets/Script/App/UI/Controllers/LeaderboardUIController.cs
  • Assets/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.

  • Assets/Script/App/Managers/InputManager.cs
  • Assets/Script/Game/Entities/Player/Core/Player.cs
  • Assets/Script/Game/Entities/Player/Core/AbilityHolder.cs
  • Assets/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.

  • Assets/Script/TinyChaos/Services/Audio/AudioService.cs
  • Assets/Script/Game/Resources/AudioResources.cs
  • Assets/Script/Game/Resources/AbilityResources.cs
  • Assets/Script/Game/Stage/DamagePopUp.cs
  • Assets/Script/Game/Utilities/Announcer.cs
  • Assets/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.

  • 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.

  • Assets/Script/App/Core/AppInitiator.cs
  • Assets/Script/App/Core/SplashUIController.cs
  • Assets/Script/App/Managers/GameSettings.cs
  • Assets/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?

Must Redesign Before Implementation

  • Ability system: do not copy AbilityHolder or 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, and PlayerAttack.
  • 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 Entity concept 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 upgradeName save 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.
  • One reusable gameplay scene.
  • Soldier / Alex spawned through PlayerManager and PlayerSpawner.
  • PC local input path for WASD, arrow-key, and gamepad-ready profiles.
  • One EntityCore shared 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.