using System; using System.Collections.Generic; using UnityEngine; namespace LiveOpsExamples { /// /// Spawns collectible snacks at random positions inside the configured bounds, /// picking a random collectible slug (moonberry/acorn/star/snack) and applying /// its sprite from the library. Mirrors GameScene.spawnCollectible. /// /// Phaser spawn margins x∈[115,1165], y∈[118,625] px on a 1280×720 field at /// 100 PPU map to x∈[-5.25,5.25], y∈[-2.65,2.42] world units (y is flipped). /// public class SnackSpawner : MonoBehaviour { private static readonly string[] CollectibleSlugs = { "moonberry", "acorn", "star", "snack" }; [SerializeField] private Snack prefab; [SerializeField] private CozyCollectorSpriteLibrary library; [SerializeField] private Vector2 spawnMin = new Vector2(-5.25f, -2.65f); [SerializeField] private Vector2 spawnMax = new Vector2(5.25f, 2.42f); [SerializeField] private Transform parent; private readonly List _spawned = new List(); public SpriteRenderer Player { get; set; } public event Action Collected; public Snack Spawn() { var slug = CollectibleSlugs[UnityEngine.Random.Range(0, CollectibleSlugs.Length)]; var position = new Vector3( UnityEngine.Random.Range(spawnMin.x, spawnMax.x), UnityEngine.Random.Range(spawnMin.y, spawnMax.y), 0f); var snack = Instantiate(prefab, position, Quaternion.identity, parent); var sprite = library.ForSlug(slug); snack.GetComponent().sprite = sprite; // Phaser setDisplaySize(52, 52) at 100 PPU -> 0.52 x 0.52 world units. var spriteBounds = sprite.bounds.size; var scale = new Vector3(0.52f / spriteBounds.x, 0.52f / spriteBounds.y, 1f); snack.transform.localScale = scale; // The prefab collider radius is tuned to snack.png; a circle collider's // world radius scales by the largest transform axis, so retune per sprite. snack.GetComponent().radius = 0.22f / Mathf.Max(scale.x, scale.y); snack.Player = Player; snack.Collected += OnSnackCollected; _spawned.Add(snack); return snack; } public void Clear() { foreach (var snack in _spawned) { if (snack == null) continue; snack.Collected -= OnSnackCollected; Destroy(snack.gameObject); } _spawned.Clear(); } private void OnSnackCollected(Snack snack) { snack.Collected -= OnSnackCollected; _spawned.Remove(snack); Collected?.Invoke(snack); } } }