Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question 2D enemy AI 4 directional attack

Discussion in '2D' started by steveyamat36, Feb 26, 2023.

  1. steveyamat36

    steveyamat36

    Joined:
    Feb 26, 2023
    Posts:
    5
    Im trying to create a 2D rpg game and I already have an enemy that detects and chases the Player whenever the Player is within range. What I want to happen is for the enemy to play an attack animation (left, right, up or down) depending on where the player is. Any help will be appreciated :).


    Heres the movement script for my enemy if it helps (its from a youtube tutorial i watched):

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class EnemyAI : MonoBehaviour
    6. {
    7.     private float angle;
    8.     public float speed;
    9.     public float checkRadius;
    10.     public float attackRadius;
    11.  
    12.     public bool chasing;
    13.  
    14.     public LayerMask whatIsPlayer;
    15.  
    16.     private Transform target, enemy;
    17.     private Rigidbody2D rb;
    18.     private Animator anim;
    19.     private Vector2 movement;
    20.     public Vector3 direction;
    21.  
    22.     private bool isInChaseRange;
    23.     private bool isInAttackRange;
    24.  
    25.     private void Start()
    26.     {
    27.         rb = GetComponent<Rigidbody2D>();
    28.         anim = GetComponent<Animator>();
    29.         target = GameObject.FindWithTag("Fighter").transform;
    30.     }
    31.     private void Update()
    32.     {
    33.         anim.SetBool("isRunning", isInChaseRange);
    34.  
    35.         isInChaseRange = Physics2D.OverlapCircle(transform.position, checkRadius, whatIsPlayer);
    36.         isInAttackRange = Physics2D.OverlapCircle(transform.position, attackRadius, whatIsPlayer);
    37.  
    38.         direction = target.position - transform.position;
    39.         angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
    40.         direction.Normalize();
    41.         movement = direction;
    42.         if(chasing)
    43.         {
    44.             anim.SetFloat("Horizontal", direction.x);
    45.             anim.SetFloat("Vertical", direction.y);
    46.         }
    47.  
    48.     }
    49.  
    50.     private void FixedUpdate()
    51.     {
    52.         if(isInChaseRange && !isInAttackRange)
    53.         {
    54.             MoveCharacter(movement);
    55.         }
    56.  
    57.         if(isInAttackRange)
    58.         {
    59.             rb.velocity = Vector2.zero;
    60.  
    61.         }
    62.     }
    63.  
    64.     private void MoveCharacter(Vector2 direction)
    65.     {
    66.         rb.MovePosition((Vector2)transform.position + (direction * Time.deltaTime));
    67.     }
    68. }
    69.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,963
    Sounds great! The necessary parts will be:

    - make 4 separate animations for each direction (start with perhaps ONE just to prove it works)
    - based on the player vs enemy position, choose which animation to play
    - play it
    - do any other damage bookkeeping.

    Which parts are you struggling with?

    How to report your problem productively in the Unity3D forums:

    http://plbm.com/?p=220

    This is the bare minimum of information to report:

    - what you want
    - what you tried
    - what you expected to happen
    - what actually happened, especially any errors you see
    - links to documentation you used to cross-check your work (CRITICAL!!!)
     
  3. steveyamat36

    steveyamat36

    Joined:
    Feb 26, 2023
    Posts:
    5
    I've done the first step (make 4 seperate animations). Now I'm struggling with how to write the code that tells whether the player is right, left, up or down of the enemy.

    I can get the enemy to attack in 1 direction but only 1.

    My Player's attack animations are based on anim.SetFloat("LastHorizontal", Input.GetAxisRaw("Horizontal")) and anim.SetFloat("LastVertical", Input.GetAxisRaw("Vertical")) so I thought I could do the same with the enemy but I realized I cant since its Input. And I dont know what the alternative is or how I should code it.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,963
    The easiest way is to see which axis (X or Y) is larger magnitude, and based on that larger axis decide which way.

    Code (csharp):
    1. // fill these in appropriately:
    2. Vector3 playerPosition = ....
    3. Vector3 enemyPosition = ...
    4.  
    5. // enemy first in subtraction means "how does the player go TO the enemy?"
    6. float deltaX = enemyPosition.x - playerPosition.x;
    7. float deltaY = enemyPosition.y - playerPosition.y;
    8.  
    9. if (Mathf.Abs( deltaX) > Mathf.Abs( deltaY))
    10. {
    11.   // must be left or right since deltaX is greater
    12.   // if (deltaX < 0) it is left...
    13.   // if (deltaX > 0) it is right...
    14. }
    15. else
    16. {
    17.   // must be up or down since deltaY is greater/equal
    18.   // if (deltaY < 0) it is down...
    19.   // if (deltaY > 0) it is up...
    20. }
    Obviously doesn't handle player / enemy at the same location. :)
     
  5. steveyamat36

    steveyamat36

    Joined:
    Feb 26, 2023
    Posts:
    5
    Thanks a lot. I've been stumped for a couple days with this one. I'll test it out later :)
     
  6. steveyamat36

    steveyamat36

    Joined:
    Feb 26, 2023
    Posts:
    5
    Yo, just an update, It works. Thanks again for the help man.

    I did it like this:

    Code (CSharp):
    1. if(isInAttackRange)
    2.         {
    3.             rb.velocity = Vector2.zero;
    4.             Vector3 playerPosition = target.position;
    5.             Vector3 enemyPosition = transform.position;
    6.  
    7.             float deltaX = enemyPosition.x - playerPosition.x;
    8.             float deltaY = enemyPosition.y - playerPosition.y;
    9.             if (Mathf.Abs( deltaX) > Mathf.Abs( deltaY) )
    10.                 {
    11.                     anim.SetBool("isAttack", true);
    12.                     anim.SetFloat("LastHorizontal", deltaX);
    13.                    
    14.                 }
    15.             else if (Mathf.Abs( deltaX) < Mathf.Abs( deltaY))
    16.                 {
    17.                     anim.SetBool("isAttack", true);
    18.                     anim.SetFloat("LastVertical", deltaY);
    19.                 }
    20.         }
     
    Kurt-Dekker likes this.