CTA33
New member
- Joined
- Feb 19, 2025
- Messages
- 1
- Programming Experience
- Beginner
my problem with this script i wrote, and ai edited/changed some, is that the enemy is supposed to switch from attacking to idle for a cooldown period and then back to attacking, while the player is in close proximity. but what happens is the cooldown fails, idle doesnt interchange with attacking, the enemy just hits and hits and hits in quick succession, and the animatiion is a little jittery. i have the proper animation events set. where is this script going wrong?? Thank you! spent many hours on this. I am a newbie. 
C#:
using UnityEngine;
public class EnemyMovement : MonoBehaviour
{
// Public variables
public Rigidbody2D rb;
public float speed = 1f;
public float attackRange = 2f;
public float attackCoolDown = 2f;
public float playerDetectRange = 5f;
public Transform detectionPoint;
public LayerMask playerLayer;
// Private variables
private Transform player;
private int facingDirection = 1;
private Animator anim;
private EnemyState enemyState;
private float attackCoolDownTimer;
private bool isAttacking;
public enum EnemyState
{
Idle,
Chasing,
Attacking,
Patrolling
}
void Start()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
ChangeState(EnemyState.Idle);
}
void Update()
{
CheckForPlayer();
UpdateCooldownTimer();
switch (enemyState)
{
case EnemyState.Chasing:
Chase();
break;
case EnemyState.Attacking:
if (!isAttacking)
{
rb.linearVelocity = Vector2.zero; // Stop movement when attacking
Attack();
}
break;
case EnemyState.Idle:
if (attackCoolDownTimer <= 0 && player != null && Vector2.Distance(transform.position, player.position) <= attackRange)
{
ChangeState(EnemyState.Attacking);
}
break;
}
}
private void UpdateCooldownTimer()
{
if (attackCoolDownTimer > 0)
{
attackCoolDownTimer -= Time.deltaTime;
Debug.Log($"Cooldown timer: {attackCoolDownTimer}");
}
}
void Chase()
{
if (player == null) return;
if (Vector2.Distance(player.position, transform.position) <= attackRange)
{
ChangeState(EnemyState.Attacking);
}
else
{
AdjustFacingDirection();
Vector2 direction = (player.position - transform.position).normalized;
rb.linearVelocity = direction * speed; // Use linearVelocity instead of velocity
}
}
private void AdjustFacingDirection()
{
if (player.position.x > transform.position.x && facingDirection < 0 ||
player.position.x < transform.position.x && facingDirection > 0)
{
Flip();
}
}
void CheckForPlayer()
{
Collider2D[] hits = Physics2D.OverlapCircleAll(detectionPoint.position, playerDetectRange, playerLayer);
Debug.Log("Checking for player...");
if (hits.Length > 0)
{
player = hits[0].transform;
Debug.Log("Player detected!");
if (Vector2.Distance(transform.position, player.position) <= attackRange && attackCoolDownTimer <= 0)
{
attackCoolDownTimer = attackCoolDown; // Reset cooldown when attacking
ChangeState(EnemyState.Attacking);
}
else if (enemyState != EnemyState.Chasing)
{
ChangeState(EnemyState.Chasing);
}
}
else
{
Debug.Log("No player detected.");
if (enemyState != EnemyState.Idle)
{
ChangeState(EnemyState.Idle);
}
}
}
void Flip()
{
facingDirection *= -1;
transform.localScale = new Vector3(transform.localScale.x * -1, transform.localScale.y, transform.localScale.z);
}
public void Attack()
{
// Implement attack logic here
Debug.Log("Attack!");
isAttacking = true;
Invoke("OnAttackAnimationEnd", 1f); // Adjust the duration as per your attack animation length
}
public void OnAttackAnimationEnd()
{
Debug.Log("Attack animation ended.");
isAttacking = false;
attackCoolDownTimer = attackCoolDown; // Reset the cooldown timer after the attack
ChangeState(EnemyState.Idle); // Switch to Idle state after attack
}
void ChangeState(EnemyState newState)
{
Debug.Log($"Changing state from {enemyState} to {newState}");
// Exit the current animation
switch (enemyState)
{
case EnemyState.Idle:
anim.SetBool("isIdle", false);
break;
case EnemyState.Chasing:
anim.SetBool("isChasing", false);
break;
case EnemyState.Attacking:
anim.SetBool("isAttacking", false);
break;
}
// Update our current state
enemyState = newState;
// Enter the new animation
switch (enemyState)
{
case EnemyState.Idle:
anim.SetBool("isIdle", true);
rb.linearVelocity = Vector2.zero; // Ensure the enemy stops moving
break;
case EnemyState.Chasing:
anim.SetBool("isChasing", true);
break;
case EnemyState.Attacking:
anim.SetBool("isAttacking", true);
rb.linearVelocity = Vector2.zero; // Ensure the enemy stops moving
break;
}
}
}
Last edited by a moderator: