196 lines
3.8 KiB
C#
196 lines
3.8 KiB
C#
using UnityEngine;
|
|
|
|
public class Enemy : MonoBehaviour, IMovementDirection
|
|
{
|
|
[Header("Movement")]
|
|
[SerializeField]
|
|
private float moveSpeed = 0.5f;
|
|
|
|
[SerializeField]
|
|
private float targetReachedDistance = 0.1f;
|
|
|
|
private EnemyTargetManager targetManager;
|
|
private Transform currentTarget;
|
|
|
|
// Wird von CharacterRotation verwendet.
|
|
public Vector2 MovementDirection { get; private set; }
|
|
|
|
[Header("Health")]
|
|
[SerializeField]
|
|
private float maxHealth = 100f;
|
|
|
|
private float currentHealth;
|
|
|
|
public float CurrentHealth => currentHealth;
|
|
|
|
public bool IsDead { get; private set; }
|
|
|
|
private void Awake()
|
|
{
|
|
currentHealth = maxHealth;
|
|
|
|
targetManager =
|
|
FindFirstObjectByType<EnemyTargetManager>();
|
|
|
|
if (targetManager == null)
|
|
{
|
|
Debug.LogError(
|
|
"Enemy: Kein EnemyTargetManager gefunden!",
|
|
this
|
|
);
|
|
}
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (targetManager != null)
|
|
{
|
|
targetManager.OnTargetsChanged +=
|
|
SelectClosestTarget;
|
|
}
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (targetManager != null)
|
|
{
|
|
targetManager.OnTargetsChanged -=
|
|
SelectClosestTarget;
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
if (targetManager == null)
|
|
return;
|
|
|
|
SelectClosestTarget();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (targetManager == null)
|
|
return;
|
|
|
|
// Kein aktuelles Ziel vorhanden.
|
|
if (currentTarget == null)
|
|
{
|
|
MovementDirection = Vector2.zero;
|
|
|
|
SelectClosestTarget();
|
|
|
|
return;
|
|
}
|
|
|
|
// Das aktuelle Ziel wurde deaktiviert.
|
|
if (!currentTarget.gameObject.activeInHierarchy)
|
|
{
|
|
SelectClosestTarget();
|
|
|
|
return;
|
|
}
|
|
|
|
MoveTowardsTarget();
|
|
|
|
// Ziel erreicht.
|
|
if (HasReachedTarget())
|
|
{
|
|
SelectClosestTarget();
|
|
}
|
|
}
|
|
|
|
|
|
// BEWEGUNGSLOGIK
|
|
//
|
|
|
|
private void SelectClosestTarget()
|
|
{
|
|
if (targetManager == null)
|
|
return;
|
|
|
|
currentTarget =
|
|
targetManager.GetClosestActiveTarget(
|
|
transform.position
|
|
);
|
|
|
|
if (currentTarget == null)
|
|
{
|
|
MovementDirection = Vector2.zero;
|
|
}
|
|
}
|
|
|
|
private void MoveTowardsTarget()
|
|
{
|
|
if (currentTarget == null)
|
|
return;
|
|
|
|
Vector3 direction =
|
|
currentTarget.position - transform.position;
|
|
|
|
MovementDirection = new Vector2(
|
|
direction.x,
|
|
direction.y
|
|
).normalized;
|
|
|
|
transform.position = Vector3.MoveTowards(
|
|
transform.position,
|
|
currentTarget.position,
|
|
moveSpeed * Time.deltaTime
|
|
);
|
|
}
|
|
|
|
private bool HasReachedTarget()
|
|
{
|
|
if (currentTarget == null)
|
|
return false;
|
|
|
|
return Vector3.Distance(
|
|
transform.position,
|
|
currentTarget.position
|
|
) <= targetReachedDistance;
|
|
}
|
|
|
|
|
|
// LEBENSLOGIK
|
|
//
|
|
|
|
public void TakeDamage(float damage)
|
|
{
|
|
if (IsDead || damage <= 0f)
|
|
return;
|
|
|
|
currentHealth -= damage;
|
|
|
|
Debug.Log(
|
|
gameObject.name +
|
|
" erhält " + damage +
|
|
" Schaden. HP: " +
|
|
currentHealth + "/" + maxHealth
|
|
);
|
|
|
|
if (currentHealth <= 0f)
|
|
{
|
|
Die();
|
|
}
|
|
}
|
|
|
|
private void Die()
|
|
{
|
|
if (IsDead)
|
|
return;
|
|
|
|
IsDead = true;
|
|
|
|
Debug.Log(
|
|
gameObject.name + " wurde besiegt!"
|
|
);
|
|
|
|
Destroy(gameObject);
|
|
}
|
|
|
|
|
|
// ANGRIFFSLOGIK (möglicherweise in anderem Skript)
|
|
//
|
|
|
|
}
|