using UnityEngine; using System.Collections; using System.Collections.Generic; public class BallSpawner : MonoBehaviour { public GameObject basicBallPrefab; public GameObject nuclearBallPrefab; public GameObject glassBallPrefab; public GameObject eyeBallPrefab; public GameObject oozeBallPrefab; public GameObject fruitBallPrefab; public GameObject gameBoard; private static WaitForSeconds _waitForSeconds0_5 = new WaitForSeconds(0.5f); private Queue ballQueue = new Queue(); private Queue balls = new Queue(); // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { int currentLevel = PlayerPrefs.GetInt("CurrentLevel"); ballQueue.Enqueue(() => SpawnBall(basicBallPrefab)); ballQueue.Enqueue(() => SpawnBall(basicBallPrefab)); ballQueue.Enqueue(() => SpawnBall(basicBallPrefab)); ballQueue.Enqueue(() => SpawnBall(fruitBallPrefab)); ballQueue.Enqueue(() => SpawnBall(fruitBallPrefab)); ballQueue.Enqueue(() => SpawnBall(oozeBallPrefab)); ballQueue.Enqueue(() => SpawnBall(nuclearBallPrefab)); ballQueue.Enqueue(() => SpawnBall(glassBallPrefab)); ballQueue.Enqueue(() => SpawnBall(glassBallPrefab)); ballQueue.Enqueue(() => SpawnBall(glassBallPrefab)); ballQueue.Enqueue(() => SpawnBall(glassBallPrefab)); ballQueue.Enqueue(() => SpawnBall(glassBallPrefab)); StartCoroutine(SpawnBalls()); } public void SpawnBallOfType(string ballType, Vector2? position = null) { switch (ballType) { case "BasicBall": SpawnBall(basicBallPrefab, position); break; case "NuclearBall": SpawnBall(nuclearBallPrefab, position); break; case "GlassBall": SpawnBall(glassBallPrefab, position); break; case "EyeBall": SpawnBall(eyeBallPrefab, position); break; case "OozeBall": SpawnBall(oozeBallPrefab, position); break; case "FruitBall": SpawnBall(fruitBallPrefab, position); break; default: Debug.LogWarning($"Unknown ball type: {ballType}"); break; } } private void SpawnBall(GameObject ballPrefab, Vector2? position = null) { if (ballPrefab == null || gameBoard == null) { Debug.LogWarning("BallSpawner: Missing ballPrefab or gameBoard reference."); return; } Vector3 spawnPosition = position.HasValue ? new Vector3(position.Value.x, position.Value.y, gameBoard.transform.position.z) : GetRandomPositionInsideGameBoard(); var newBall = Instantiate(ballPrefab, spawnPosition, Quaternion.identity); if (ballPrefab == oozeBallPrefab) { var oozeBallScript = newBall.GetComponent(); if (oozeBallScript != null) { oozeBallScript.spawner = this; } } balls.Enqueue(newBall); FixCollisions(); } private Vector3 GetRandomPositionInsideGameBoard() { Bounds bounds; Collider2D collider2D = gameBoard.GetComponent(); if (collider2D != null) { bounds = collider2D.bounds; } else { Renderer boardRenderer = gameBoard.GetComponent(); if (boardRenderer == null) { Debug.LogWarning("BallSpawner: gameBoard needs a Collider2D or Renderer to read bounds."); return gameBoard.transform.position; } bounds = boardRenderer.bounds; } const float edgeInset = 0.05f; float randomX = Random.Range(bounds.min.x + edgeInset, bounds.max.x - edgeInset); float randomY = Random.Range(bounds.min.y + edgeInset, bounds.max.y - edgeInset); return new Vector3(randomX, randomY, gameBoard.transform.position.z); } public void FixCollisions() { // Disable collision between existing balls of certain types. // Only basic balls and fruit balls will collide with each other, while ooze, // nuclear, glass, and eye balls will not collide with any other balls. // As an exception, glass balls will collide with other glass balls. foreach (var ball in balls) { foreach (var otherBall in balls) { if (ball == otherBall) continue; bool ballIsBasicOrFruit = ball.CompareTag("BasicBall") || ball.CompareTag("FruitBall"); bool otherIsBasicOrFruit = otherBall.CompareTag("BasicBall") || otherBall.CompareTag("FruitBall"); bool bothAreGlass = ball.CompareTag("GlassBall") && otherBall.CompareTag("GlassBall"); bool shouldCollide = (ballIsBasicOrFruit && otherIsBasicOrFruit) || bothAreGlass; if (!shouldCollide) { Physics2D.IgnoreCollision( ball.GetComponent(), otherBall.GetComponent(), true ); } } } } private IEnumerator SpawnBalls() { while (ballQueue.Count > 0) { System.Action spawnAction = ballQueue.Dequeue(); spawnAction.Invoke(); yield return _waitForSeconds0_5; } FixCollisions(); } }