Gegnerpathing Logik
This commit is contained in:
@@ -1,45 +1,189 @@
|
||||
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 closestDistanceSqr = float.MaxValue;
|
||||
float closestDistance = float.MaxValue;
|
||||
|
||||
foreach (Transform target in targetPoints)
|
||||
{
|
||||
if (target == null || !target.gameObject.activeInHierarchy)
|
||||
continue;
|
||||
|
||||
float distanceSqr =
|
||||
(target.position - position).sqrMagnitude;
|
||||
|
||||
if (distanceSqr < closestDistanceSqr)
|
||||
if (target == null ||
|
||||
!target.gameObject.activeInHierarchy)
|
||||
{
|
||||
closestDistanceSqr = distanceSqr;
|
||||
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);
|
||||
}
|
||||
else if (Mathf.Approximately(
|
||||
distanceSqr,
|
||||
closestDistanceSqr))
|
||||
// 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;
|
||||
}
|
||||
|
||||
int randomIndex = Random.Range(
|
||||
// Bei mehreren gleich nahen Targets zufällig wählen.
|
||||
int randomIndex = UnityEngine.Random.Range(
|
||||
0,
|
||||
closestTargets.Count
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user