144 lines
5.1 KiB
C#
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);
|
|
}*/
|
|
}
|