using UnityEngine; public class EnemyController : MonoBehaviour { private PlayerController player; public float moveSpeed, chaseRange = 15f, stopCloseRange = 4f, strafeAmount, pointWaitTimer = 3f, currentHealth = 25f, waitToDisappear = 4f; public Rigidbody theRB; public Animator anim; public Transform[] PatrolPoints; private int currentPatrolPoint; public Transform pointsHolder; private float waitCounter; private bool isDead; private float attackCooldown = 1f; // Time between attacks in seconds private float attackTimer = 0f; // Timer to track attack cooldown // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { player = FindFirstObjectByType(); strafeAmount = Random.Range(-0.75f, 0.75f); pointsHolder.SetParent(null); // Detach pointsHolder from any parent to avoid unwanted transformations waitCounter = Random.Range(0.75f, 1.25f) * pointWaitTimer; attackTimer = 0f; } // Update is called once per frame void Update() { if (isDead) { waitToDisappear -= Time.deltaTime; // Decrease the timer for disappearing if (waitToDisappear <= 0) { transform.localScale = Vector3.MoveTowards(transform.localScale, Vector3.zero, Time.deltaTime * 2f); // Gradually shrink the enemy if (transform.localScale.magnitude < 0.1f) { Destroy(gameObject); // Destroy the enemy after it has shrunk Destroy(pointsHolder.gameObject); // Also destroy the pointsHolder if it's no longer needed } } return; // Exit if the enemy is dead } attackTimer -= Time.deltaTime; // Update attack cooldown timer float yStore = theRB.linearVelocity.y; float distance = Vector3.Distance(player.transform.position, transform.position); if (distance < chaseRange) { transform.LookAt(new Vector3(player.transform.position.x, transform.position.y, player.transform.position.z)); if (distance > stopCloseRange) { theRB.linearVelocity = (transform.forward + transform.right * strafeAmount) * moveSpeed; anim.SetBool("isRunning", true); anim.SetBool("isWalking", false); } else { theRB.linearVelocity = Vector3.zero; anim.SetBool("isWalking", false); anim.SetBool("isRunning", false); // Only trigger attack if cooldown has expired if (attackTimer <= 0f) { anim.SetTrigger("attack"); attackTimer = attackCooldown; // Reset attack timer } } } else { if (PatrolPoints.Length > 0) { if (Vector3.Distance(transform.position, new Vector3(PatrolPoints[currentPatrolPoint].position.x, transform.position.y, PatrolPoints[currentPatrolPoint].position.z)) < 0.25f) { waitCounter -= Time.deltaTime; theRB.linearVelocity = Vector3.zero; anim.SetBool("isWalking", false); anim.SetBool("isRunning", false); if (waitCounter <= 0) { currentPatrolPoint++; if (currentPatrolPoint >= PatrolPoints.Length) { currentPatrolPoint = 0; } waitCounter = Random.Range(0.75f, 1.25f) * pointWaitTimer; } } else { transform.LookAt(new Vector3(PatrolPoints[currentPatrolPoint].position.x, transform.position.y, PatrolPoints[currentPatrolPoint].position.z)); theRB.linearVelocity = transform.forward * moveSpeed; anim.SetBool("isWalking", true); anim.SetBool("isRunning", false); } } else { theRB.linearVelocity = Vector3.zero; anim.SetBool("isWalking", false); anim.SetBool("isRunning", false); } } theRB.linearVelocity = new Vector3(theRB.linearVelocity.x, yStore, theRB.linearVelocity.z); } // This method will be called by Animation Events at the specific frame in the attack animation public void DealDamage() { // Check if player is still in range when the damage frame occurs if (Vector3.Distance(player.transform.position, transform.position) < 2f) { PlayerHealthController.instance.TakeDamage(5f); } } public void TakeDamage(float damageToTake) { currentHealth -= damageToTake; // Reduce current health by the damage taken if (currentHealth <= 0) { anim.SetTrigger("dead"); isDead = true; theRB.linearVelocity = Vector3.zero; // Stop movement when dead theRB.isKinematic = true; // Make the Rigidbody kinematic to stop physics interactions theRB.angularVelocity = Vector3.zero; // Stop rotation when dead GetComponent().enabled = false; // Disable collider to prevent further interactions } } }