1
0
Files
LupiNexMedia 01eb521da8 Initial commit
2026-06-04 03:42:31 +02:00

205 lines
7.6 KiB
C#

using UnityEngine;
using System.Collections.Generic;
public class SpawnManager : MonoBehaviour
{
private float[] spawnPositionsEnemiesOppositeZ = { 3.7f, 11f, 17.8f, 24.6f, 31.8f, 39f };
private float[] spawnPositionsEnemiesForwardsZ = { -3.7f, -11f, -17.8f, -24.6f, -31.8f, -39f };
private float[] spawnPositionsObstaclesZ = { 3.7f, 11f, 17.8f, 24.6f, 31.8f, 39f, -3.7f, -11f, -17.8f, -24.6f, -31.8f, -39f };
private float spawnPositionSafezoneZ = -39f;
private float? safezoneZ = null;
private float safezoneTime = 10f;
private float safezoneStopX = 0f;
public GameObject safezonePrefab;
private List<float> occupiedZPositions = new List<float>();
public GameObject[] enemyPrefabs;
public GameObject[] obstaclePrefabs;
private List<Rigidbody> activeEnemies = new List<Rigidbody>();
private List<Rigidbody> activeObstacles = new List<Rigidbody>();
public float vehicleSpeed = 75f;
public float despawnX = 50f;
private PlayerController playerControllerScript;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
playerControllerScript = GameObject.Find("Player").GetComponent<PlayerController>();
float spawnInterval = Random.Range(1.8f, 2.3f);
float safezoneInterval = Random.Range(20f, 30f);
InvokeRepeating("SpawnRandomObject", 10f, spawnInterval);
InvokeRepeating("SpawnSafezone", 0f, safezoneInterval);
}
void SpawnRandomObject()
{
if (playerControllerScript.gameOver)
return;
occupiedZPositions.Clear();
// Wie viele Objekte gleichzeitig spawnen sollen (zufällig oder fix)
int objectsToSpawn = Random.Range(1, 10); // 1 bis 9 pro Spawn-Aufruf
for (int i = 0; i < objectsToSpawn; i++)
{
float rand = Random.value;
if (rand < 0.6f)
SpawnRandomEnemy();
else
SpawnRandomObstacle();
}
}
void FixedUpdate()
{
if (!playerControllerScript.gameOver)
{
// Gegner bewegen
for (int i = activeEnemies.Count - 1; i >= 0; i--)
{
Rigidbody rb = activeEnemies[i];
if (rb == null) { activeEnemies.RemoveAt(i); continue; }
rb.AddForce(rb.gameObject.GetComponent<MoveData>().moveDir * 6, ForceMode.Force);
if (Mathf.Abs(rb.position.x) > despawnX)
{
occupiedZPositions.Remove(rb.position.z); // Z wieder freigeben
Destroy(rb.gameObject);
activeEnemies.RemoveAt(i);
}
}
// Hindernisse bewegen
for (int i = activeObstacles.Count - 1; i >= 0; i--)
{
Rigidbody rb = activeObstacles[i];
if (rb == null) { activeObstacles.RemoveAt(i); continue; }
rb.AddForce(rb.gameObject.GetComponent<MoveData>().moveDir * 6, ForceMode.Force);
if (Mathf.Abs(rb.position.x) > despawnX)
{
occupiedZPositions.Remove(rb.position.z);
Destroy(rb.gameObject);
activeObstacles.RemoveAt(i);
}
}
foreach (var safezone in GameObject.FindObjectsOfType<SafezoneData>())
{
Rigidbody rb = safezone.GetComponent<Rigidbody>();
if (rb == null) continue;
// Prüfen, ob Stop erreicht
if (rb.position.x > safezone.stopX || safezone.playerOn)
{
rb.AddForce(safezone.moveDir * 2, ForceMode.Force); // bewegt sich
}
else
{
rb.linearVelocity = Vector3.zero; // stoppt
safezone.waitTime -= Time.fixedDeltaTime;
if (safezone.waitTime <= 0f)
{
// Player ist nicht drauf -> Game Over
PlayerController pc = GameObject.Find("Player").GetComponent<PlayerController>();
if (!safezone.playerHasBeenOn)
pc.gameOver = true;
Destroy(safezone.gameObject); // Safezone weg
safezoneZ = null;
}
}
}
}
}
void SpawnRandomEnemy()
{
GameObject chosenPrefab = enemyPrefabs[Random.Range(0, enemyPrefabs.Length)];
bool spawnOpposite = Random.value > 0.5f;
float[] possibleZ = spawnOpposite ? spawnPositionsEnemiesOppositeZ : spawnPositionsEnemiesForwardsZ;
// Filtere belegte Z-Positionen heraus
List<float> availableZ = new List<float>();
foreach (var z in possibleZ)
if (!occupiedZPositions.Contains(z) && z != safezoneZ)
availableZ.Add(z);
if (availableZ.Count == 0)
return; // keine freie Spur
float chosenZ = availableZ[Random.Range(0, availableZ.Count)];
occupiedZPositions.Add(chosenZ);
Vector3 spawnPos = spawnOpposite ? new Vector3(40f, 0.5f, chosenZ) : new Vector3(-40f, 0.5f, chosenZ);
Vector3 moveForce = spawnOpposite ? Vector3.left * vehicleSpeed : Vector3.right * vehicleSpeed;
GameObject enemy = Instantiate(chosenPrefab, spawnPos, chosenPrefab.transform.rotation);
Rigidbody rb = enemy.GetComponent<Rigidbody>();
if (rb != null)
{
rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
MoveData data = enemy.AddComponent<MoveData>();
data.moveDir = moveForce;
activeEnemies.Add(rb);
}
}
void SpawnRandomObstacle()
{
GameObject chosenPrefab = obstaclePrefabs[Random.Range(0, obstaclePrefabs.Length)];
// Filtere belegte Z-Positionen
List<float> availableZ = new List<float>();
foreach (var z in spawnPositionsObstaclesZ)
if (!occupiedZPositions.Contains(z) && z != safezoneZ)
availableZ.Add(z);
if (availableZ.Count == 0)
return; // keine freie Spur
float chosenZ = availableZ[Random.Range(0, availableZ.Count)];
occupiedZPositions.Add(chosenZ);
Vector3 spawnPos = new Vector3(40f, 0.5f, chosenZ);
GameObject obstacle = Instantiate(chosenPrefab, spawnPos, chosenPrefab.transform.rotation);
Rigidbody rb = obstacle.GetComponent<Rigidbody>();
if (rb != null)
{
rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
MoveData data = obstacle.AddComponent<MoveData>();
data.moveDir = Vector3.left * vehicleSpeed;
activeObstacles.Add(rb);
}
}
void SpawnSafezone()
{
if (safezonePrefab == null) return;
Vector3 spawnPos = new Vector3(40f, 0.5f, spawnPositionSafezoneZ);
GameObject safezone = Instantiate(safezonePrefab, spawnPos, safezonePrefab.transform.rotation);
safezoneZ = spawnPositionSafezoneZ;
Rigidbody rb = safezone.GetComponent<Rigidbody>();
if (rb != null)
{
rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
SafezoneData data = safezone.AddComponent<SafezoneData>();
data.moveDir = Vector3.left * vehicleSpeed; // fährt nach -X
data.stopX = safezoneStopX;
data.waitTime = safezoneTime;
}
}
}
public class MoveData : MonoBehaviour
{
public Vector3 moveDir;
}