using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.Tilemaps; public class ObjectSpawner : MonoBehaviour { public enum ObjectType { Enemy } public Tilemap tilemap; public GameObject[] objectPrefabs; // Only Enemy prefab should be in this array public float enemyProbability = 0.1f; // Not used if only spawning enemies public int maxObjects = 2; // Maximum number of objects to spawn public float enemySpawnDelay = 1f; // seconds between spawns private List validSpawnPositions = new List(); private List spawnObjects = new List(); private Coroutine spawnCoroutine; void Start() { GetValidSpawns(); StartSpawnCoroutine(); GameController.OnReset += LevelChange; } void Update() { // Only spawn if the hub is not active GameObject hub = GameObject.Find("Hub"); if (hub != null && hub.activeSelf) return; if (!tilemap.gameObject.activeInHierarchy) { LevelChange(); } } private void LevelChange() { tilemap = GameObject.Find("Platforms").GetComponent(); GetValidSpawns(); DestroyAllObjects(); StartSpawnCoroutine(); } private int ActiveObjectsCount() { spawnObjects.RemoveAll(obj => obj == null); return spawnObjects.Count; } private void StartSpawnCoroutine() { if (spawnCoroutine != null) StopCoroutine(spawnCoroutine); spawnCoroutine = StartCoroutine(SpawnObjectsToMaxCoroutine()); } private IEnumerator SpawnObjectsToMaxCoroutine() { while (ActiveObjectsCount() < maxObjects) { SpawnObject(); yield return new WaitForSeconds(enemySpawnDelay); } } private ObjectType RandomObjectType() { return ObjectType.Enemy; } private void SpawnObject() { spawnObjects.RemoveAll(obj => obj == null); GameObject player = GameObject.FindGameObjectWithTag("Player"); Vector3 playerPos = player != null ? player.transform.position : Vector3.zero; List availablePositions = new List(); foreach (var pos in validSpawnPositions) { bool occupied = spawnObjects.Any(obj => obj != null && obj.transform.position == pos); // Use OverlapCircle to check for player at spawn position bool playerHere = Physics2D.OverlapCircle(pos, 0.5f, LayerMask.GetMask("Player")); bool tooClose = Vector3.Distance(pos, playerPos) < 3f; if (!occupied && !playerHere && !tooClose) availablePositions.Add(pos); } if (availablePositions.Count == 0) return; Vector3 spawnPosition = availablePositions[Random.Range(0, availablePositions.Count)]; ObjectType objectType = RandomObjectType(); GameObject gameObject = Instantiate(objectPrefabs[(int)objectType], spawnPosition, Quaternion.identity); spawnObjects.Add(gameObject); } private void DestroyAllObjects() { foreach (GameObject obj in spawnObjects) { if (obj != null) { Destroy(obj); } } spawnObjects.Clear(); } private void GetValidSpawns() { 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); } } } } public void NotifyObjectDestroyed(GameObject obj) { if (spawnObjects.Contains(obj)) { spawnObjects.Remove(obj); if (ActiveObjectsCount() < maxObjects) { StartSpawnCoroutine(); } } } }