134 lines
5.4 KiB
C#
134 lines
5.4 KiB
C#
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<PlayerController>();
|
|
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<Collider>().enabled = false; // Disable collider to prevent further interactions
|
|
}
|
|
}
|
|
}
|