using System; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.Serialization; using Random = UnityEngine.Random; public class CatchMinigameManager : MonoBehaviour { private int _score; public int Score { get => _score; set { _score = value; scoreText.text = "Score: " + _score + " / " + minimalScore; } } private int _netAttempts; public int NetAttempts { get => _netAttempts; set { _netAttempts = value; netAttemptText.text = "Netten over: " + (maxNetAttempts - value) + " / " + maxNetAttempts; } } public float minSpawnForce = 100; public float maxSpawnForce = 400; public Transform leftSpawnPoint; public Transform rightSpawnPoint; public Collider duckCaughtCollider; public TMP_Text scoreText; public TMP_Text netAttemptText; [FormerlySerializedAs("MInigameInstruction")] public MinigameInstruction minigameInstruction; public float netCooldown = 0.5f; public float netVelocity = 10f; public Vector3 netDisplacement = Vector3.up * 4; public int maxNetAttempts = 5; public int minimalScore = 20; public GameObject net; public ParticleSystem duckCollectEffect; // When ducks leave the river bounds, they're disabled public Bounds riverBounds; public float avgSpawnsPerSecond = 5; public Transform duckParent; public Transform duckCollectEffectParent; public FloatingDuckController floatingDuckPrefab; public event EventHandler MinigameFinished; private List activeDucks = new List(); private Queue floatingDuckPool = new Queue(); private Queue duckCollectEffectPool = new Queue(); private bool _netMoving = false; private static CatchMinigameManager _instance; public static CatchMinigameManager Instance { get { return _instance; } private set { _instance = value; } } public CatchMinigameManager() { Instance = this; } public void ResetMinigame() { Score = 0; NetAttempts = 0; for (var i = 0; i < activeDucks.Count; i++) { floatingDuckPool.Enqueue(activeDucks[i]); activeDucks[i].gameObject.SetActive(false); } activeDucks.Clear(); minigameInstruction.Show(); } void Update() { var spawnChance = Time.deltaTime * avgSpawnsPerSecond; if (Random.value <= spawnChance) { var left = leftSpawnPoint.position; var right = rightSpawnPoint.position; var diff = left - right; var pos = right + (diff * Random.value); FloatingDuckController duck; if (floatingDuckPool.Count > 0) { duck = floatingDuckPool.Dequeue(); var duckTransform = duck.transform; duckTransform.position = pos; duckTransform.rotation = Quaternion.identity; duck.initialForce = Vector3.left * ((maxSpawnForce - minSpawnForce) * Random.value); duck.gameObject.SetActive(true); } else { duck = Instantiate(floatingDuckPrefab, pos, Quaternion.identity, duckParent); duck.initialForce = Vector3.left * ((maxSpawnForce - minSpawnForce) * Random.value); duck.duckCaughtCollider = duckCaughtCollider; duck.DuckCaught += (obj, args) => { Score++; DisableDuck(duck); if (duckCollectEffect != null) { ParticleSystem effect; if (duckCollectEffectPool.Count > 0) { effect = duckCollectEffectPool.Dequeue(); effect.gameObject.SetActive(true); effect.transform.position = duck.transform.position; } else { effect = Instantiate(duckCollectEffect, duck.transform.position, duckCollectEffect.transform.rotation, duckCollectEffectParent); } effect.Play(); StartCoroutine(PoolEffectWhenFinished(effect)); } }; } activeDucks.Add(duck); } for (var i = 0; i < activeDucks.Count; i++) { var duck = activeDucks[i]; if (!riverBounds.Contains(duck.transform.position)) { DisableDuck(i); i--; } } if (Input.GetMouseButtonDown(0) && !_netMoving) { // Activate the net NetAttempts++; StartCoroutine(MoveNet()); } if (!_netMoving && NetAttempts >= maxNetAttempts) { // Minigame finished if (MinigameFinished != null) { MinigameFinished.Invoke(this, Score >= minimalScore ? MiniGameResult.Success : MiniGameResult.Failed); } } } private IEnumerator PoolEffectWhenFinished(ParticleSystem effect) { while (effect.isPlaying) { yield return null; } effect.gameObject.SetActive(false); duckCollectEffectPool.Enqueue(effect); } private void DisableDuck(FloatingDuckController duck) { DisableDuck(activeDucks.IndexOf(duck)); } private void DisableDuck(int i) { var duck = activeDucks[i]; activeDucks.RemoveAt(i); duck.gameObject.SetActive(false); floatingDuckPool.Enqueue(duck); } private IEnumerator MoveNet() { _netMoving = true; var totalTime = netDisplacement.magnitude / netVelocity; var time = 0f; var originalNetPosition = net.transform.position; while (time < totalTime) { time += Time.deltaTime; net.transform.position = originalNetPosition + (netDisplacement * (time / totalTime)); yield return null; } time = 0f; while (time < netCooldown) { time += Time.deltaTime; net.transform.position = originalNetPosition + netDisplacement - (netDisplacement * (time / netCooldown)); yield return null; } net.transform.position = originalNetPosition; _netMoving = false; } } public enum MiniGameResult { Success, Failed }