194 lines
4.9 KiB
C#
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];
|
|
}
|
|
}
|