using UnityEngine; using System; using System.Collections; namespace Minigames.DivingForPictures { public class Monster : MonoBehaviour { [Header("References")] [SerializeField] private CircleCollider2D detectionCollider; private bool pictureAlreadyTaken = false; private Camera mainCamera; // Events public event Action OnPictureTaken; public event Action OnMonsterSpawned; public event Action OnMonsterDespawned; // Properties public float PictureRadius => detectionCollider != null ? detectionCollider.radius : 0f; private void Awake() { if (detectionCollider == null) detectionCollider = GetComponent(); mainCamera = Camera.main; // Start checking if monster is off-screen StartCoroutine(CheckIfOffScreen()); } private void OnEnable() { pictureAlreadyTaken = false; OnMonsterSpawned?.Invoke(this); } private IEnumerator CheckIfOffScreen() { WaitForSeconds wait = new WaitForSeconds(0.5f); while (true) { yield return wait; if (!IsVisibleToCamera()) { DespawnMonster(); yield break; } } } private bool IsVisibleToCamera() { if (mainCamera == null) mainCamera = Camera.main; if (mainCamera == null) return false; // Get the world position (will account for parent movement) Vector3 worldPosition = transform.position; Vector3 viewportPoint = mainCamera.WorldToViewportPoint(worldPosition); // Adjust buffer to be larger below the screen to account for downward movement float bufferSides = 0.2f; float bufferTop = 0.2f; float bufferBottom = 0.5f; // Larger buffer below the screen return viewportPoint.x > -bufferSides && viewportPoint.x < 1 + bufferSides && viewportPoint.y > -bufferBottom && viewportPoint.y < 1 + bufferTop; } private void OnTriggerEnter2D(Collider2D other) { // Check if it's the player if (other.CompareTag("Player") && !pictureAlreadyTaken) { TakePicture(); } } // Called when a picture is taken of this monster public void TakePicture() { if (pictureAlreadyTaken) return; pictureAlreadyTaken = true; OnPictureTaken?.Invoke(this); DespawnMonster(); } // Public method to despawn this monster public void DespawnMonster() { if (gameObject.activeSelf) { OnMonsterDespawned?.Invoke(this); gameObject.SetActive(false); Destroy(gameObject); } } // Visualization for the picture radius in editor private void OnDrawGizmosSelected() { // Get the collider in edit mode if (detectionCollider == null) detectionCollider = GetComponent(); if (detectionCollider != null) { Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(transform.position, detectionCollider.radius / 2); } } #if UNITY_EDITOR // Update collider radius in editor private void OnValidate() { if (detectionCollider == null) detectionCollider = GetComponent(); } #endif } }