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.
Enemy And Spawn System¶
Purpose¶
The enemy/spawn system controls wave schedules, special/miniboss timing, boss transitions, enemy state machines, enemy damage/death/rewards, and battlefield cleanup.
Current Unity Implementation¶
Main scripts:
| Path | Script | Role |
|---|---|---|
Assets/Script/Game/Entities/EnemySpawner/SpawnerData.cs |
SpawnerData, SpawnEvent |
Time-window spawn schedule data. |
Assets/Script/Game/Entities/EnemySpawner/SpawnerEventManager.cs |
SpawnerEventManager |
Runtime wave, special, and boss spawn controller. |
Assets/Script/Game/Entities/Enemies/Enemy.cs |
Enemy |
Enemy core: stats, state machine, target, damage, death, rewards, CC. |
Assets/Script/Game/Entities/Enemies/Boss.cs |
Boss |
Boss subtype data: spawn delay/effect/icon/music. |
Assets/Script/Game/Entities/Enemies/EnemyCore/EnemyBaseState.cs |
EnemyBaseState |
Base enemy state behavior and transitions. |
Assets/Script/Game/Entities/Enemies/EnemyCore/EnemyAttackState.cs |
EnemyAttackState |
Attack cooldown/animation/range state base. |
Assets/Script/Game/Entities/Enemies/EnemyState/*.cs |
ES*, EAS* |
Movement and attack states. |
Assets/Script/Game/Entities/Enemies/Mechanic/*.cs |
EM* |
Reusable enemy mechanics like timed ability, summon, bullet shoot, mortar, heat. |
Assets/Script/Game/Entities/Enemies/Boss/*.cs |
SA* |
Boss-specific special attacks. |
Key Data¶
SpawnEvent fields:
timeSpawn: start time.maxTimeToSpawn: end time.enemy: prefab to spawn.spawnRate: delay between spawns for this event.spawnTop,spawnBottom,spawnLeft,spawnRight,spawnRandom: spawn direction flags.isSpawning,isActive: runtime flags stored on spawn data object.
SpawnerEventManager key fields:
battleState:Battle,MinibossFight,BossFight,GameOver.bossIsActive,isMiniBossSpawn.boss,CreepSpawnData,SpecialSpawnData,EndGameTime.healthBar,timerBar,bossIcon.minibossFightTimer: suppresses creep spawning for special/miniboss events.
Enemy key data:
- Type:
EnemyType.Creep,Miniboss,Boss,Special. - Health/damage:
maxHealth, difficulty health bonus,damage,DamageResistance. - Death/reward:
killId,deathAnimationTime,reward,exp,gold,score,chaosFragment. - State:
currentState,availableStates. - CC: poison/burn/freeze/stun dictionaries and modifiers.
- Target: nearest player reference and position.
Runtime Flow¶
Spawn Initialization¶
GameInitialization.PrepareSpawnAndGameManagerData()selects the current difficulty's creep and specialSpawnerData, end game time, and boss.SpawnerEventManager.StartTheInitialization()waits forspawnerManagerInit.- It caches
Camera.main.gameObject, setsbattleState = Battle, and resets allisSpawning/isActiveflags in both spawner data assets.
Creep Spawning¶
SpawnerEventManager.Update()callsCreepSpawnSystem().- Each creep spawn event is checked against
Timer.currentSpawnerTime. - If within the event window and
battleState == Battle, event is active. - If not already spawning and no special/miniboss is active, it starts
SpawnEnemy(). SpawnEnemy()waitsspawnRate, calculates an off-camera position based on direction flags, and gets the enemy fromPoolManager.- For creep enemies,
isSpawningis reset to false after one spawn, allowing repeated spawns on the schedule.
Special / Miniboss Spawning¶
SpecialSpawnSystem()checks special spawn data againstTimer.currentTime.- If a special/miniboss event starts,
isMiniBossSpawnis set. minibossFightTimeris set to:- 60 seconds for
EnemyType.Miniboss. - 10 seconds for
EnemyType.Special. - While
isMiniBossSpawnis true, creep spawn coroutines are blocked. - If a special/miniboss dies and its
killIdmatches special spawn data,MiniBossDeath()clearsisMiniBossSpawnand resets creep spawn active/spawning flags.
Boss Transition¶
- If a spawn event's enemy is
EnemyType.Boss,SpawnEnemy()setsbattleState = BossFight, plays boss music, and stops normal spawn. - In
SpecialSpawnSystem(), whenbattleState == BossFightand no boss is active, it startsSpawnBoss(). SpawnBoss()stops timers, locks the camera, makes all current enemies flee, waits, spawns boss effect, waits boss delay, spawns boss, binds boss health bar, animates boss UI, and moves timer bar.- On boss death,
BossDeathFunc()startsChangeStage(). ChangeStage()restarts timers, clears creep flags, returns toBattle, hides boss UI, and unlocks camera following.
Enemy Runtime¶
Enemy.OnEnable()resets status, applies difficulty health, finds nearest player, resets death/flee/CC state, emitsGameEvents.OnEnemySpawn, loads first state.Enemy.Update()updates health bar, sprite flip, border death timer, state machine, CC timers, aggro timer, and cached player position.EnemyBaseStateand subclasses control movement/attack transitions.Enemy.TakeDamage()subtracts damage, spawns damage popup, invokes damage event, retargets, handles knockback/blood/blink, and triggers death.Enemy.Death()emits enemy death/counter/target removal, adds score/chaos, plays audio, starts death animation, and drops rewards.- Rewards are spawned from enemy reward tables as pooled
Items.
Dependencies¶
- Spawner depends on
GameManager.instance.Timer,PoolManager,Camera.main,AudioResources,Game.Audio,Announcer, DOTween. - Enemy depends on
Difficulty,GameEvents,GameManager,GameSession,PoolManager,UIResourceProvider,Save, audio resources, camera. - Player target tracking depends on enemy spawn/remove events.
Problems / Risks¶
- Runtime flags are stored on
SpawnerDataScriptableObject assets. - Special/miniboss spawn suppression is a hardcoded 10/60 second rule. If a kill event is missed, the game may appear to stall until the timer expires.
CheckSpecialKillIdcallsGetComponent<Enemy>()on spawner prefab entries repeatedly.SpawnBoss()usesGameObject.FindGameObjectsWithTag("Enemy")to make all enemies flee.Enemy.FindNearestPlayerandEnemy.FindNearestEnemyuse scene-wide tag searches.Enemy.Update()does many responsibilities per enemy every frame.DeathTimer()checks camera/screen bounds every frame per enemy.- Reward spawning can create many pooled items; pool can grow without prewarm or cap.
Enemy.Rewarding()checksreward.Length == 0 || reward == nullin unsafe order. Ifrewardis null,reward.Lengthwould throw. Unknown if Unity inspector guarantees non-null arrays here.
Migration Notes for Godot¶
Preserve:
- Spawn windows, spawn rates, directions, special/miniboss suppression, boss transition behavior.
- Enemy types and reward drops.
- Difficulty health scaling.
- Enemy state machine concepts.
- Player target add/remove event behavior.
- Boss UI/lock-camera phase.
Redesign:
SpawnScheduleResource
- immutable spawn event data
SpawnDirector
- owns runtime event state
- tracks active event ids separately from data
- emits boss_started, boss_defeated, special_started, special_cleared
EnemyScene
- HealthComponent
- EnemyStateMachine
- EnemyRewardDropper
- EnemyTargeting
- CrowdControlComponent
Use Godot groups for enemies/players, but avoid full group scans in hot paths. Prefer:
- spawn/remove events into target registries,
- spatial queries for nearby enemies,
- cached player list from
PlayerManager.
Do not copy:
- Runtime mutation of spawn data resources.
- Tag search targeting loops.
- One large enemy script with state, reward, damage, and targeting all together.
Open Questions¶
- Is the 60-second miniboss spawn suppression intended to feel like a wave pause?
- What should happen if a miniboss leaves/dies by border timeout without matching
killId? - Does every enemy prefab have valid
HitPointsand state arrays? - Unknown / needs manual confirmation.