Files
DepthsOfGreed/Assets/Scripts/EnemyTargetManager.cs
T
2026-10-07 14:40:02 +02:00

194 lines
4.9 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyTargetManager : MonoBehaviour
{
[Header("Target Points")]
[SerializeField]
private List<Transform> targetPoints = new List<Transform>();
[Header("Active Target Chance")]
[SerializeField]
[Range(0f, 1f)]
private float twoTargetsChance = 0.25f;
[Header("Switch Timing")]
[SerializeField]
private float minSwitchDelay = 15f;
[SerializeField]
private float maxSwitchDelay = 25f;
[Header("Target Selection")]
[SerializeField]
[Min(0f)]
private float equalDistanceTolerance = 0.1f; //In Unity-Einheiten!
// Wird ausgelöst, wenn sich die aktiven Ziele ändern.
public event Action OnTargetsChanged;
private void Start()
{
if (targetPoints.Count == 0)
{
Debug.LogError(
"EnemyTargetManager: Keine Target Points zugewiesen!",
this
);
return;
}
if (targetPoints.Count < 2)
{
Debug.LogWarning(
"EnemyTargetManager: Es sind weniger als 2 Target Points vorhanden. Zwei aktive Targets sind dadurch nicht möglich.",
this
);
}
if (minSwitchDelay > maxSwitchDelay)
{
Debug.LogWarning(
"EnemyTargetManager: minSwitchDelay ist größer als maxSwitchDelay. Werte werden getauscht.",
this
);
float temp = minSwitchDelay;
minSwitchDelay = maxSwitchDelay;
maxSwitchDelay = temp;
}
// Zu Beginn zufällig Targets aktivieren.
SetRandomActiveTargets();
// Danach regelmäßig wechseln.
StartCoroutine(TargetSwitchLoop());
}
private IEnumerator TargetSwitchLoop()
{
while (true)
{
float delay = UnityEngine.Random.Range(
minSwitchDelay,
maxSwitchDelay
);
yield return new WaitForSeconds(delay);
SetRandomActiveTargets();
}
}
private void SetRandomActiveTargets()
{
// Zuerst alle Targets deaktivieren.
foreach (Transform target in targetPoints)
{
if (target != null)
{
target.gameObject.SetActive(false);
}
}
// Entscheiden, ob 1 oder 2 Targets aktiv sein sollen.
int activeTargetCount = 1;
if (targetPoints.Count >= 2 &&
UnityEngine.Random.value < twoTargetsChance)
{
activeTargetCount = 2;
}
// Alle gültigen Targets sammeln.
List<Transform> availableTargets =
new List<Transform>();
foreach (Transform target in targetPoints)
{
if (target != null)
{
availableTargets.Add(target);
}
}
// Zufällige Targets aktivieren.
for (int i = 0; i < activeTargetCount; i++)
{
int randomIndex = UnityEngine.Random.Range(
0,
availableTargets.Count
);
Transform target =
availableTargets[randomIndex];
target.gameObject.SetActive(true);
// Verhindert doppelte Auswahl.
availableTargets.RemoveAt(randomIndex);
}
// Alle Gegner informieren.
OnTargetsChanged?.Invoke();
}
public Transform GetClosestActiveTarget(Vector3 position)
{
List<Transform> closestTargets =
new List<Transform>();
float closestDistance = float.MaxValue;
foreach (Transform target in targetPoints)
{
if (target == null ||
!target.gameObject.activeInHierarchy)
{
continue;
}
// Tatsächliche Entfernung in Unity-Einheiten.
float distance =
Vector3.Distance(
position,
target.position
);
// Eindeutig näher als die bisher gefundenen Targets.
if (distance <
closestDistance - equalDistanceTolerance)
{
closestDistance = distance;
closestTargets.Clear();
closestTargets.Add(target);
}
// Innerhalb der eingestellten Toleranz:
// Dieses Target gilt als gleich nah.
else if (Mathf.Abs(
distance - closestDistance
) <= equalDistanceTolerance)
{
closestTargets.Add(target);
}
}
if (closestTargets.Count == 0)
{
return null;
}
// Bei mehreren gleich nahen Targets zufällig wählen.
int randomIndex = UnityEngine.Random.Range(
0,
closestTargets.Count
);
return closestTargets[randomIndex];
}
}