using UnityEngine; using Core; using Core.Settings; using Core.Lifecycle; using AppleHillsCamera; namespace Minigames.BirdPooper { /// /// Spawns targets at regular intervals for Bird Pooper minigame. /// Uses Transform references for spawn and despawn positions. /// All targets are spawned at Y = 0 (EdgeAnchor positions them vertically). /// public class TargetSpawner : ManagedBehaviour { [Header("Spawn Configuration")] [Tooltip("Transform marking where targets spawn (off-screen right)")] [SerializeField] private Transform spawnPoint; [Tooltip("Transform marking where targets despawn (off-screen left)")] [SerializeField] private Transform despawnPoint; [Header("EdgeAnchor References")] [Tooltip("ScreenReferenceMarker to pass to spawned targets")] [SerializeField] private ScreenReferenceMarker referenceMarker; [Tooltip("CameraScreenAdapter to pass to spawned targets")] [SerializeField] private CameraScreenAdapter cameraAdapter; [Header("Target Prefabs")] [Tooltip("Array of target prefabs to spawn randomly")] [SerializeField] private GameObject[] targetPrefabs; private IBirdPooperSettings settings; private float spawnTimer; private bool isSpawning; internal override void OnManagedAwake() { base.OnManagedAwake(); // Load settings settings = GameManager.GetSettingsObject(); if (settings == null) { Debug.LogError("[TargetSpawner] BirdPooperSettings not found!"); return; } // Validate references if (spawnPoint == null) { Debug.LogError("[TargetSpawner] Spawn Point not assigned! Please assign a Transform in the Inspector."); } if (despawnPoint == null) { Debug.LogError("[TargetSpawner] Despawn Point not assigned! Please assign a Transform in the Inspector."); } if (targetPrefabs == null || targetPrefabs.Length == 0) { Debug.LogError("[TargetSpawner] No target prefabs assigned! Please assign at least one prefab in the Inspector."); } if (referenceMarker == null) { Debug.LogError("[TargetSpawner] ScreenReferenceMarker not assigned! Targets need this for EdgeAnchor positioning."); } if (cameraAdapter == null) { Debug.LogWarning("[TargetSpawner] CameraScreenAdapter not assigned. EdgeAnchor will attempt to auto-find camera."); } Debug.Log("[TargetSpawner] Initialized successfully"); } private void Update() { if (!isSpawning || settings == null) return; spawnTimer += Time.deltaTime; if (spawnTimer >= settings.TargetSpawnInterval) { SpawnTarget(); spawnTimer = 0f; } } /// /// Spawns a random target prefab at the spawn point. /// Target is spawned at Y = 0, EdgeAnchor will position it vertically. /// private void SpawnTarget() { if (targetPrefabs == null || targetPrefabs.Length == 0 || spawnPoint == null) { Debug.LogError("[TargetSpawner] Cannot spawn target - missing prefabs or spawn point!"); return; } // Randomly select target prefab GameObject prefab = targetPrefabs[Random.Range(0, targetPrefabs.Length)]; // Spawn at spawn point X, but Y = 0 (EdgeAnchor will position vertically) Vector3 spawnPosition = new Vector3(spawnPoint.position.x, 0f, 0f); GameObject targetObj = Instantiate(prefab, spawnPosition, Quaternion.identity); // Initialize target Target target = targetObj.GetComponent(); if (target != null) { float despawnX = despawnPoint != null ? despawnPoint.position.x : -12f; target.Initialize(despawnX, referenceMarker, cameraAdapter); // Subscribe to target hit event to notify manager target.onTargetHit.AddListener(OnTargetHit); Debug.Log($"[TargetSpawner] Spawned target at {spawnPosition}"); } else { Debug.LogError($"[TargetSpawner] Spawned prefab '{prefab.name}' does not have Target component!"); Destroy(targetObj); } } /// /// Called when a target is hit by a projectile. /// Notifies the game manager for score tracking. /// private void OnTargetHit() { // Find and notify manager BirdPooperGameManager manager = BirdPooperGameManager.Instance; if (manager != null) { manager.OnTargetHit(); } else { Debug.LogWarning("[TargetSpawner] BirdPooperGameManager not found!"); } } /// /// Start spawning targets at regular intervals. /// public void StartSpawning() { isSpawning = true; spawnTimer = 0f; Debug.Log("[TargetSpawner] Started spawning targets"); } /// /// Stop spawning new targets (existing targets continue). /// public void StopSpawning() { isSpawning = false; Debug.Log("[TargetSpawner] Stopped spawning targets"); } /// /// Check if spawner is currently spawning. /// public bool IsSpawning => isSpawning; /// /// Draw gizmos to visualize spawn and despawn points in the editor. /// private void OnDrawGizmos() { if (spawnPoint != null) { Gizmos.color = Color.cyan; Gizmos.DrawLine( new Vector3(spawnPoint.position.x, -10f, 0f), new Vector3(spawnPoint.position.x, 10f, 0f) ); } if (despawnPoint != null) { Gizmos.color = Color.magenta; Gizmos.DrawLine( new Vector3(despawnPoint.position.x, -10f, 0f), new Vector3(despawnPoint.position.x, 10f, 0f) ); } } } }