Files
AppleHillsProduction/docs/airplane_spawn_system_guide.md
Michal Pikulski 7ce6d914e6 Stash work
2025-12-07 20:34:43 +01:00

12 KiB

Airplane Spawn System - Implementation Summary

Overview

The spawn system dynamically generates targets, positive/negative objects, and ground tiles as the airplane flies through the level. It consists of three main components:

  1. AirplaneSpawnManager - Core spawning logic
  2. TargetDisplayUI - Real-time distance display
  3. Settings Integration - Configurable spawn parameters

Components Created

1. AirplaneSpawnManager

File: Assets/Scripts/Minigames/Airplane/Core/AirplaneSpawnManager.cs

Responsibilities:

  • Spawn target at predetermined distance on game start
  • Extract target icon sprite for UI display
  • Track airplane movement and trigger dynamic spawning after threshold
  • Spawn positive/negative objects at random intervals with weighted ratio
  • Spawn ground tiles at regular intervals
  • Clean up spawned objects between turns

Key Features:

  • Target Dictionary: Serializable array converted to dictionary for fast lookup
  • Weighted Spawning: Adjusts positive/negative spawn probability to maintain target ratio
  • Threshold-Based: Spawning only begins when plane crosses configured X position
  • Automatic Icon Extraction: Finds first SpriteRenderer in target prefab for UI

2. TargetDisplayUI

File: Assets/Scripts/Minigames/Airplane/UI/TargetDisplayUI.cs

Responsibilities:

  • Display target icon
  • Show real-time distance to target
  • Update distance as airplane moves

Key Features:

  • Performance Optimization: Updates every N frames (configurable)
  • Flexible Format: Configurable distance display format string
  • Lifecycle Management: Hides on start, shows when tracking begins

3. Settings Updates

Files:

  • Assets/Scripts/Core/Settings/SettingsInterfaces.cs (IAirplaneSettings)
  • Assets/Scripts/Minigames/Airplane/Settings/AirplaneSettings.cs

New Settings Added:

// Spawn System
float DynamicSpawnThreshold          // X position where spawning begins
float TargetMinDistance              // Min random distance for target
float TargetMaxDistance              // Max random distance for target
float ObjectSpawnMinInterval         // Min time between object spawns
float ObjectSpawnMaxInterval         // Max time between object spawns
float PositiveNegativeRatio          // 0-1 ratio (1=all positive, 0=all negative)
float SpawnDistanceAhead            // Distance ahead of plane to spawn objects
float GroundSpawnInterval           // Distance between ground tiles

Game Flow Integration

Initialization (SetupNextPerson)

SetupNextPerson()
├─ Post-shot reaction (if not first turn)
├─ Get next person
├─ Introduce person
├─ spawnManager.InitializeForGame(targetName)
│  ├─ Determine random target distance
│  ├─ Calculate target spawn position
│  ├─ Spawn target at position
│  ├─ Extract sprite from target
│  └─ Setup UI with sprite and position
├─ Set expected target in validator
└─ Enter aiming state

Launch (HandleAirplaneLaunched)

HandleAirplaneLaunched()
├─ Disable launch controller
├─ Change state to Flying
├─ Start camera following airplane
├─ spawnManager.StartTracking(airplane.transform)
│  ├─ Store plane transform
│  ├─ Initialize ground spawn position
│  └─ Start UI tracking (show distance)
└─ Subscribe to airplane events

During Flight (Update Loop)

SpawnManager.Update()
├─ Check if plane crossed threshold
│  └─ If yes: Initialize dynamic spawning
├─ If past threshold:
│  ├─ Check spawn timer
│  │  └─ If time: Spawn random object + schedule next
│  └─ Check ground spawn distance
│     └─ If passed: Spawn ground tile + increment position
└─ (UI updates distance every N frames)

Cleanup (EvaluateResult)

EvaluateResult()
├─ Stop camera following
├─ spawnManager.StopTracking()
│  └─ Hide UI
├─ Evaluate success/failure
├─ Destroy airplane
├─ spawnManager.CleanupSpawnedObjects()
│  ├─ Destroy all spawned objects
│  ├─ Destroy all ground tiles
│  └─ Destroy spawned target
└─ Continue to next person

Spawning Logic Details

Target Spawning (Game Start)

  1. Called: When person's turn begins, before aiming
  2. Distance: Random between TargetMinDistance and TargetMaxDistance
  3. Position: Vector3(distance, 0, 0) - adjust Y as needed
  4. Icon Extraction: Searches target and children for first SpriteRenderer
  5. UI Setup: Passes sprite and position to TargetDisplayUI

Dynamic Object Spawning (After Threshold)

  1. Trigger: When plane X position >= DynamicSpawnThreshold
  2. Interval: Random between ObjectSpawnMinInterval and ObjectSpawnMaxInterval
  3. Type Selection: Weighted randomness based on PositiveNegativeRatio
    • First 5 spawns: Pure random based on ratio
    • Subsequent spawns: Adjusts probability to maintain target ratio
  4. Position: planePosition + Vector3.right * SpawnDistanceAhead
  5. Prefab: Random selection from positive or negative array

Ground Tile Spawning (After Threshold)

  1. Trigger: When plane X position >= nextGroundSpawnX
  2. Interval: Regular distance intervals (GroundSpawnInterval)
  3. Position: Vector3(nextGroundSpawnX, 0, 0) - adjust Y as needed
  4. Prefab: Random selection from ground tile array

Weighted Ratio Algorithm

// If current ratio is below target:
//   Increase positive spawn probability
// If current ratio is above target:
//   Decrease positive spawn probability

adjustedProbability = currentRatio < targetRatio
    ? Lerp(targetRatio, 1.0, (targetRatio - currentRatio) * 2)
    : Lerp(0.0, targetRatio, 1 - (currentRatio - targetRatio) * 2);

Unity Setup

AirplaneSpawnManager Component

Inspector Fields:

  • Target Prefabs: Array of TargetPrefabEntry (key + prefab)
  • Positive Object Prefabs: Array of prefabs to spawn as positive
  • Negative Object Prefabs: Array of prefabs to spawn as negative
  • Ground Tile Prefabs: Array of prefabs to spawn as ground
  • Target Display UI: Reference to TargetDisplayUI component
  • Spawned Objects Parent: Optional transform for organization
  • Ground Tiles Parent: Optional transform for organization

TargetDisplayUI Component

Inspector Fields:

  • Target Icon: Image component to show target sprite
  • Distance Text: TextMeshProUGUI to show distance
  • Distance Format: String format (default: "{0:F1}m")
  • Update Interval: Frames between updates (default: 5, 0=every frame)

Scene Hierarchy

AirplaneGameManager
├─ PersonQueue
├─ CameraManager
├─ LaunchController
├─ TargetValidator
├─ SpawnManager (NEW)
│  ├─ SpawnedObjects (empty parent)
│  └─ GroundTiles (empty parent)
└─ Canvas
   └─ TargetDisplayUI (NEW)
      ├─ TargetIcon (Image)
      └─ DistanceText (TextMeshProUGUI)

Settings Configuration

Path: Tools > Settings > Airplane Settings

Spawn System Section:

  • Dynamic Spawn Threshold: 10f
  • Target Min Distance: 30f
  • Target Max Distance: 50f
  • Object Spawn Min Interval: 1f
  • Object Spawn Max Interval: 3f
  • Positive Negative Ratio: 0.5f (50/50 split)
  • Spawn Distance Ahead: 15f
  • Ground Spawn Interval: 5f

Prefab Requirements

Target Prefabs

  • Must Have: At least one SpriteRenderer (for icon extraction)
  • Must Have: Unique key for dictionary lookup
  • Should Have: Collider2D with "Is Trigger" enabled
  • Should Have: AirplaneTarget component

Positive/Negative Object Prefabs

  • No specific requirements
  • Suggestion: Add Collider2D if you want collision detection
  • Suggestion: Add scripts for behavior/scoring

Ground Tile Prefabs

  • No specific requirements
  • Suggestion: Size should match GroundSpawnInterval for seamless tiling

API Reference

AirplaneSpawnManager

Public Methods

// Initialize for new game - spawns target, sets up UI
void InitializeForGame(string targetKey)

// Start tracking airplane and enable spawning
void StartTracking(Transform planeTransform)

// Stop spawning and tracking
void StopTracking()

// Clean up all spawned objects
void CleanupSpawnedObjects()

// Get target info (position, distance, sprite)
(Vector3 position, float distance, Sprite icon) GetTargetInfo()

TargetDisplayUI

Public Methods

// Setup display with target sprite and position
void Setup(Sprite targetSprite, Vector3 targetPosition)

// Start tracking airplane and showing distance
void StartTracking(Transform planeTransform)

// Stop tracking and hide UI
void StopTracking()

// Show/hide UI
void Show()
void Hide()

Testing Checklist

Pre-Flight

  • Spawn Manager assigned in Game Manager
  • Target prefabs configured with keys matching Person target names
  • Positive/Negative object prefabs assigned
  • Ground tile prefabs assigned
  • Target Display UI created and assigned
  • Settings configured with desired spawn parameters

In-Game

  • Target spawns at game start at correct distance
  • Target Display UI shows correct icon
  • Distance updates as plane moves
  • Dynamic spawning begins after threshold
  • Objects spawn ahead of plane at intervals
  • Positive/negative ratio maintained over time
  • Ground tiles spawn at regular intervals
  • All spawned objects cleaned up between turns

Performance Considerations

Optimizations Included

  • UI updates every N frames instead of every frame
  • Dictionary lookup for target prefabs (O(1) vs O(n))
  • Objects parented for easy batch cleanup
  • Single Update loop for all spawning logic

Potential Issues

  • Too Many Objects: Adjust spawn intervals or add object pooling
  • Memory Leaks: CleanupSpawnedObjects destroys everything between turns
  • Spawn Lag: All spawns are instantaneous - consider staggering if needed

Extension Points

Easy Additions

  1. Object Pooling: Replace Instantiate/Destroy with pool system
  2. Spawn Variety: Add more object types with different spawn rules
  3. Vertical Spawning: Add Y-axis randomness to spawn positions
  4. Spawn Waves: Add wave-based spawning patterns
  5. Distance-Based Difficulty: Increase spawn frequency as distance increases
  6. Score Integration: Add scoring when collecting positive/avoiding negative

Integration with Existing Systems

  • Collision Detection: Spawned objects can use existing collision systems
  • Audio: Trigger sounds on spawn using AudioManager
  • VFX: Add particle effects at spawn positions
  • UI: Extend TargetDisplayUI to show additional info (score, bonuses, etc.)

Common Issues & Solutions

Target Not Spawning

  • Check targetKey matches Person.TargetName exactly
  • Verify target prefab is assigned in Target Prefabs array
  • Check InitializeForGame is called in SetupNextPerson

Wrong Icon Displayed

  • Ensure target prefab has SpriteRenderer component
  • Check SpriteRenderer has sprite assigned
  • Try adding SpriteRenderer as direct child of target root

Objects Spawn Too Early/Late

  • Adjust DynamicSpawnThreshold setting
  • Check plane transform is correctly passed to StartTracking

Ratio Not Maintained

  • Algorithm self-adjusts after first 5 spawns
  • Check PositiveNegativeRatio setting (0-1 range)
  • Increase spawn count to see ratio converge

Performance Issues

  • Increase TargetDisplayUI.UpdateInterval
  • Add object pooling for frequently spawned objects
  • Move spawned objects to separate layer for culling

Future Improvements

Suggested Enhancements

  1. Procedural Target Placement: Place targets based on level difficulty
  2. Spawn Patterns: Predefined patterns for objects (waves, formations)
  3. Environmental Objects: Non-interactive background objects for depth
  4. Dynamic Ground: Ground that reacts to plane (dust trails, etc.)
  5. Collectibles: Special objects that grant bonuses
  6. Obstacles: Dynamic obstacles that require avoidance
  7. Weather Effects: Spawned particles for wind, clouds, etc.
  8. Distance Markers: Visual indicators every X distance

Advanced Features

  1. Level Data: Scriptable objects defining spawn sequences
  2. Biomes: Different visual themes at different distances
  3. Events: Special spawn events at certain distances
  4. Multipliers: Chain spawning based on player performance
  5. Achievements: Track spawn-related statistics