Files
CastleDefence/Assets/Scripts/EnemyController.cs
2026-04-02 16:20:38 +01:00

144 lines
5.1 KiB
C#

using System.Linq;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AI;
public enum TargetType { Gate, Wall, Tower, Any }
public class EnemyController : MonoBehaviour
{
public float moveSpeed;
public float targetRange;
public float attackRange;
public float attackSpeed;
public float attackDamage;
public TargetType targetType;
public Transform target;
private NavMeshAgent navMeshAgent;
private Animator animator;
private SphereCollider targetCollider;
private float attackCooldown;
void Awake()
{
navMeshAgent = GetComponent<NavMeshAgent>();
animator = GetComponentInChildren<Animator>();
targetCollider = GetComponentInChildren<SphereCollider>();
navMeshAgent.speed = moveSpeed;
targetCollider.radius = targetRange;
}
void Start()
{
GetTarget(targetType);
}
void Update()
{
if (target != null && !target.gameObject.activeInHierarchy)
{
target = null;
GetTarget(targetType);
}
if (target != null)
Attack();
animator.SetFloat("Speed", navMeshAgent.velocity.magnitude);
}
private void OnTriggerEnter(Collider other)
{
if (target != null) return;
if (!other.CompareTag("Gate")) return;
AttackPoint attackPoint = other.GetComponentInChildren<AttackPoint>();
if (attackPoint != null && targetType == TargetType.Any)
{
target = attackPoint.transform;
navMeshAgent.stoppingDistance = attackRange;
navMeshAgent.destination = attackPoint.transform.position;
}
}
private void GetTarget(TargetType targetType)
{
GameObject[] potentialTargets;
GameObject closest = null;
float minDistance = Mathf.Infinity;
switch (targetType)
{
case TargetType.Gate:
potentialTargets = GameObject.FindGameObjectsWithTag("Gate");
foreach (GameObject go in potentialTargets)
{
float distance = Vector3.Distance(go.transform.position, transform.position);
if (distance < minDistance) { minDistance = distance; closest = go; }
}
break;
case TargetType.Wall:
potentialTargets = GameObject.FindGameObjectsWithTag("Wall");
foreach (GameObject go in potentialTargets)
{
float distance = Vector3.Distance(go.transform.position, transform.position);
if (distance < minDistance) { minDistance = distance; closest = go; }
}
break;
case TargetType.Tower:
potentialTargets = GameObject.FindGameObjectsWithTag("Tower");
foreach (GameObject go in potentialTargets)
{
float distance = Vector3.Distance(go.transform.position, transform.position);
if (distance < minDistance) { minDistance = distance; closest = go; }
}
break;
case TargetType.Any:
potentialTargets = GameObject.FindGameObjectsWithTag("Gate")
.Concat(GameObject.FindGameObjectsWithTag("Wall"))
.Concat(GameObject.FindGameObjectsWithTag("Tower")).ToArray();
foreach (GameObject go in potentialTargets)
{
float distance = Vector3.Distance(go.transform.position, transform.position);
if (distance < minDistance) { minDistance = distance; closest = go; }
}
break;
}
if (closest != null)
{
AttackPoint attackPoint = closest.GetComponentInChildren<AttackPoint>();
if (attackPoint != null)
{
target = attackPoint.transform;
navMeshAgent.stoppingDistance = attackRange;
navMeshAgent.destination = target.position;
}
}
}
private void Attack()
{
attackCooldown -= Time.deltaTime;
if (Vector3.Distance(target.position, transform.position) < attackRange && attackCooldown <= 0f)
{
transform.LookAt(target.position);
animator.SetTrigger("Attack");
attackCooldown = 1f / attackSpeed;
target.GetComponent<AttackPoint>().AddAttacker();
target.GetComponentInParent<Building>().TakeDamage(attackDamage);
}
}
/*private void OnDrawGizmosSelected()
{
// Target range — green if priority target is assigned, red if not
Gizmos.color = target != null ? Color.green : Color.red;
Gizmos.DrawWireSphere(transform.position, targetRange);
// Attack range — green if target is within attack range, red if not
bool inAttackRange = target != null && Vector3.Distance(target.position, transform.position) < attackRange;
Gizmos.color = inAttackRange ? Color.green : Color.red;
Gizmos.DrawWireSphere(transform.position, attackRange);
}*/
}