using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Tilemaps; public class ObjectSpawner : MonoBehaviour { public enum ObjectType { Coin } public Tilemap tilemap; public GameObject[] objectPrefabs; // 0 = Coin public float coinProbability = 1.0f; // 100% Chance of coins spawning public int maxObjects = 5; public float coinLifetime = 10f; // Coins Slowly Fade Away public float spawnInterval = 0.5f; private List validSpawnPositions = new List(); private List spawnObjects = new List(); private bool isSpawning = false; void Start() { GatherValidPositions(); StartCoroutine(SpawnObjectsIfNeeded()); GameController.OnReset += LevelChange; } //Update is called once per frame void Update() { if (!tilemap.gameObject.activeInHierarchy) { LevelChange(); } if (!isSpawning && ActiveObjectsCount() < maxObjects) { StartCoroutine(SpawnObjectsIfNeeded()); } } private void LevelChange() { tilemap = GameObject.Find("Ground").GetComponent(); GatherValidPositions(); DestoryAllSpawnedObjects(); } private int ActiveObjectsCount() { spawnObjects.RemoveAll(item => item == null); return spawnObjects.Count; } private IEnumerator SpawnObjectsIfNeeded() { isSpawning = true; while (ActiveObjectsCount() < maxObjects) { SpawnObject(); yield return new WaitForSeconds(spawnInterval); } isSpawning = false; } private bool PositionHasObject(Vector3 positionToCheck) { return spawnObjects.Any(checkObj => checkObj && Vector3.Distance(checkObj.transform.position, positionToCheck) < 1.0f); } private void SpawnObject() { if (validSpawnPositions.Count == 0) return; Vector3 spawnPosition = Vector3.zero; bool validPositionFound = false; while (!validPositionFound && validSpawnPositions.Count > 0) { int randomIndex = Random.Range(0, validSpawnPositions.Count); Vector3 potentialPosition = validSpawnPositions[randomIndex]; Vector3 leftPosition = potentialPosition + Vector3.left; Vector3 rightPosition = potentialPosition + Vector3.right; if (!PositionHasObject(leftPosition) && !PositionHasObject(rightPosition)) { spawnPosition = potentialPosition; validPositionFound = true; } validSpawnPositions.RemoveAt(randomIndex); } if (validPositionFound) { ObjectType objectType = ObjectType.Coin; // Only Coin for now GameObject gameObject = Instantiate(objectPrefabs[(int)objectType], spawnPosition, Quaternion.identity); spawnObjects.Add(gameObject); StartCoroutine(DestroyObjectAfterTime(gameObject, coinLifetime)); } } private IEnumerator DestroyObjectAfterTime(GameObject gameObject, float time) { yield return new WaitForSeconds(time); if (gameObject) { spawnObjects.Remove(gameObject); validSpawnPositions.Add(gameObject.transform.position); Destroy(gameObject); } } private void DestoryAllSpawnedObjects() { foreach (GameObject obj in spawnObjects) { if (obj != null) { Destroy(obj); } } spawnObjects.Clear(); } private void GatherValidPositions() { validSpawnPositions.Clear(); BoundsInt boundsInt = tilemap.cellBounds; TileBase[] allTiles = tilemap.GetTilesBlock(boundsInt); Vector3 start = tilemap.CellToWorld(new Vector3Int(boundsInt.xMin, boundsInt.yMin, 0)); for (int x = 0; x < boundsInt.size.x; x++) { for (int y = 0; y < boundsInt.size.y; y++) { TileBase tile = allTiles[x + y * boundsInt.size.x]; if (tile != null) { Vector3 place = start + new Vector3(x + 0.5f, y + 1.5f, 0); validSpawnPositions.Add(place); } } } } }