199 lines
6.7 KiB
C#
199 lines
6.7 KiB
C#
using UnityEngine;
|
|
using Core;
|
|
using Core.Settings;
|
|
using Core.Lifecycle;
|
|
using AppleHillsCamera;
|
|
|
|
namespace Minigames.BirdPooper
|
|
{
|
|
/// <summary>
|
|
/// 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).
|
|
/// </summary>
|
|
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<IBirdPooperSettings>();
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Spawns a random target prefab at the spawn point.
|
|
/// Target is spawned at Y = 0, EdgeAnchor will position it vertically.
|
|
/// </summary>
|
|
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<Target>();
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when a target is hit by a projectile.
|
|
/// Notifies the game manager for score tracking.
|
|
/// </summary>
|
|
private void OnTargetHit()
|
|
{
|
|
// Find and notify manager
|
|
BirdPooperGameManager manager = BirdPooperGameManager.Instance;
|
|
if (manager != null)
|
|
{
|
|
manager.OnTargetHit();
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("[TargetSpawner] BirdPooperGameManager not found!");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Start spawning targets at regular intervals.
|
|
/// </summary>
|
|
public void StartSpawning()
|
|
{
|
|
isSpawning = true;
|
|
spawnTimer = 0f;
|
|
Debug.Log("[TargetSpawner] Started spawning targets");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stop spawning new targets (existing targets continue).
|
|
/// </summary>
|
|
public void StopSpawning()
|
|
{
|
|
isSpawning = false;
|
|
Debug.Log("[TargetSpawner] Stopped spawning targets");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if spawner is currently spawning.
|
|
/// </summary>
|
|
public bool IsSpawning => isSpawning;
|
|
|
|
/// <summary>
|
|
/// Draw gizmos to visualize spawn and despawn points in the editor.
|
|
/// </summary>
|
|
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)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|