using System; using System.Collections.Generic; using System.Linq; using Mapbox.CheapRulerCs; using Mapbox.Unity.Map; using UnityEngine; public class CollectableDuckManager : MonoBehaviour { public List collectableDucks; private readonly HashSet _collectedDucks = new HashSet(); private readonly Dictionary _spawnedDucks = new Dictionary(); public AbstractMap map; public Transform player; public Transform collectableDuckParent; public event EventHandler DuckClicked; /// /// Spawn distance in meters (i.e. how close should the player be to a duck before it spawns on the map /// public float spawnDistance = 50; public CollectableDuck duckSpawnPrefab; private static CollectableDuckManager _instance; public static CollectableDuckManager Instance { get { return _instance; } private set { _instance = value; } } public CollectableDuckManager() { Instance = this; } private void Awake() { CheckCollectableDuckIds(); _collectedDucks.Clear(); foreach (var duck in collectableDucks.Where(duck => PlayerPrefs.GetInt("duck." + duck.Id) > 0)) { _collectedDucks.Add(duck); } } private void CheckCollectableDuckIds() { var duckIds = new HashSet(); foreach (var duck in collectableDucks) { if (duckIds.Contains(duck.Id)) { Debug.LogError("Duplicate duck ID: '" + duck.Id + "' for duck '" + duck.name + "'"); } duckIds.Add(duck.Id); } } private void Update() { var ruler = new CheapRuler(map.CenterLatitudeLongitude.x, CheapRulerUnits.Meters); var playerPosition = map.WorldToGeoPosition(player.position).ToArray(); for (int i = 0; i < collectableDucks.Count; i++) { var duck = collectableDucks[i]; var duckCoord = duck.LatitudeLongitude; var dist = ruler.Distance(duckCoord.ToArray(), playerPosition); // Debug.Log("Distance to " + duck.name + ": " + dist); if (dist < spawnDistance && !_collectedDucks.Contains(duck)) { SpawnDuck(duck); } else { RemoveDuck(duck); } } } private void SpawnDuck(CollectableDuckData duck) { if (!_spawnedDucks.ContainsKey(duck)) { // Spawn the duck var duckSpawn = Instantiate(duckSpawnPrefab, map.GeoToWorldPosition(duck.LatitudeLongitude), Quaternion.identity, collectableDuckParent); duckSpawn.CollectableDuckData = duck; var duckModel = Instantiate(duck.ModelPrefab, duckSpawn.transform); duckModel.transform.localPosition = Vector3.zero; _spawnedDucks[duck] = duckSpawn; } else { if (!_spawnedDucks[duck].gameObject.activeSelf) { _spawnedDucks[duck].gameObject.SetActive(true); } } } private void RemoveDuck(CollectableDuckData duck) { if (_spawnedDucks.ContainsKey(duck)) { if (_spawnedDucks[duck].gameObject.activeSelf) { _spawnedDucks[duck].gameObject.SetActive(false); } } } public void OnDuckClicked(CollectableDuckData duck) { if (DuckClicked != null) { DuckClicked.Invoke(this, duck); } } public void OnDuckCollected(CollectableDuckData duck) { _collectedDucks.Add(duck); PlayerPrefs.SetInt("duck." + duck.Id, 1); RemoveDuck(duck); } }