How can i make the attack state of my FSM work?/ Unity

42 views Asked by At

Hey guys please check my fsm here my attack state doesn’t seem to work and idk why. If anyone knows please please help thank you.This script is quite long so please bare with me and thank you, If you see stuff you think i can do to improve my work please tell me so i know for the future cause i'm currently only intermediate lvl eish still lots to learn.

public class PlagueFiniteStateMachine : MonoBehaviour
{        
    public enum doctorState
    {
        // define every state needed
        Walking,
        Attack,
        Charge,
        Return,
        Idle,
        Follow,
    }

    [SerializeField] float visibleDis= 15f;
    [SerializeField] float visibleAngle= 10f;
    [SerializeField] int attack= 10;
    [SerializeField] float distance = 5f;

    private Animator ani;
    public LayerMask ignore;

    [SerializeField] private GameObject player;
    [SerializeField] NavMeshAgent plague;
    [SerializeField] GameObject targetPos;
    [SerializeField] GameObject aiBase;
    [SerializeField] GameObject vaccine;

    [SerializeField]GameObject Indicator;
    PlayerMovement op;

    //[SerializeField]Vector3 destination;

    doctorState currentState;
    
    void Start()
    {
        Indicator.SetActive(false);

        plague = GetComponent<NavMeshAgent>();
        ani = this.GetComponent<Animator>();
        op = GetComponent<PlayerMovement>();

        player = GameObject.FindGameObjectWithTag("Player");

        targetPos = GameObject.FindGameObjectWithTag("Flag");
        aiBase = GameObject.FindGameObjectWithTag("AIBase");
        vaccine = GameObject.FindGameObjectWithTag("Flag");

        ChangeState(doctorState.Walking); // on entry walking state is default state
        plague.SetDestination(targetPos.transform.position);
    }
   
    void Update()
    {
        float stillAttack = Vector3.Distance(player.transform.position, plague.transform.position);

        StateHandler();
        if (stillAttack <= distance)
        {
            ChangeState(doctorState.Attack);

            plague.SetDestination(player.transform.position);
            op.takeDamage(attack);
        }
    }

    // method to handle behaviours between states & conditions to switch states 
    void StateHandler()
    {
        switch (currentState)
        {
          case doctorState.Walking:
                if (CanSeePlayer())
                {
                    ChangeState(doctorState.Charge);
                }
                else if (CanAttack())
                {
                    ChangeState(doctorState.Attack);
                }
                else if (ReachedTarget())
                {
                    ChangeState(doctorState.Return);
                }
                break;

            case doctorState.Attack:
                if(CanSeePlayer())
                {
                    ChangeState(doctorState.Charge);
                }
                else if (!CanAttack())
                {
                    ChangeState(doctorState.Walking);
                }
                else if(ReachedTarget())
                {
                    ChangeState(doctorState.Return);
                }                
                break;
            
               case doctorState.Charge:
                if (!CanSeePlayer())
                {
                    ChangeState(doctorState.Walking);
                }
                else if(CanAttack())
                {
                    ChangeState(doctorState.Attack);
                }
                else if (ReachedTarget())
                {
                    ChangeState(doctorState.Return);
                }
                break;

                case doctorState.Return:
                if (AgentReturnedVaccine()) 
                {
                    Debug.Log("Agent secured the package, We have failed.");
                    ChangeState(doctorState.Idle);
                }
                break;      
        }                     
    }

    // method to handle the behaviour in transition between states
    void ChangeState(doctorState newState)
    { 
        if(currentState== newState) return; // to prevent unnecessary transitions;

        currentState= newState;

        //here is the enter logic for current states

        switch (currentState)
        {
            case doctorState.Walking:
                OnEnterWalking();
                break;

              case doctorState.Charge:
                OnEnterCharge();
                break;

               case doctorState.Attack:
                OnEnterAttack();
                break;

                case doctorState.Idle:
                  OnEnterIdle();
                  return;

                 case doctorState.Return:
                  OnEnterReturn();
                  break;
        }           
    }

    // Enter and exit methods for each state
    void OnEnterWalking()
    {
        ani.SetBool("CanAttack", false);
        ani.SetBool("CanCharge", false);
        ani.SetBool("IsWalking", true);
       
        plague.SetDestination(targetPos.transform.position);
       
        Debug.Log("Current state is:  " + currentState);
    }
    
    void OnEnterIdle()
    {
        Indicator.SetActive(false);

        ani.SetBool("CanAttack", false);
        ani.SetBool("CanCharge", false);
        ani.SetBool("IsWalking", false);
        ani.SetBool("IsIdle", true);           

        Debug.Log("Current state is:  " + currentState);
    }

    void OnEnterCharge()
    {
        Indicator.SetActive(false);

        ani.SetBool("IsWalking", false);
        ani.SetBool("CanAttack", false);
        ani.SetBool("CanCharge", true);
       
        plague.SetDestination(player.transform.position);

        Debug.Log("Current state is:  " + currentState);
    }

    void OnEnterAttack()
    {
        Indicator.SetActive(false);
       // float stillAttack = Vector3.Distance(player.transform.position, plague.transform.position);

        ani.SetBool("CanCharge", false);
        ani.SetBool("IsWalking", false);
        ani.SetBool("CanAttack", true);
        /*
        if(stillAttack<= distance)
        {
            plague.SetDestination(player.transform.position);
            op.takeDamage(attack);
        }
       */

        Debug.Log("Current state is:  " + currentState);
    }

    void OnEnterReturn()
    {
        Indicator.SetActive(true);

        ani.SetBool("IsWalking", false);
        ani.SetBool("CanAttack", false);
        ani.SetBool("CanCharge", true);

        plague.SetDestination(aiBase.transform.position);
        Debug.Log("Current state is:  " + currentState);
    }

    bool Captured(Collider other)
    {
        string thisTag = "Agent";
        GameObject someObject = GameObject.FindGameObjectWithTag(thisTag);
        if (other.gameObject.tag == "flag" && someObject != null)
        {
            return true;
        }
        return false;
    }

    public bool CanSeePlayer() // boolean method to check if player is in range
    {
       Vector3 direction=  player.transform.position- this.transform.position;
         float angle= Vector3.Angle(direction, this.transform.forward);

        if(direction.magnitude< visibleDis && angle< visibleAngle)
        {
            return true;
        }
        return false;
    }

    public bool CanAttack()
    {
        /*
         RaycastHit hit;
         int maxDis = 5;
        ;

         if(Physics.Raycast(transform.position, Vector3.forward, maxDis,  ignore ))
         {
             Debug.DrawRay(transform.position, transform.forward, Color.red);
             Debug.Log("Hit " + player);
             return true;
         }
         return false;
        */
        if(Vector3.Distance(player.transform.position,plague.transform.position) <= distance)
        {
            return true;
        }
        return false;
    }

    bool ReachedTarget()
    {
        if(Vector3.Distance(targetPos.transform.position, plague.transform.position) < distance)
        {
            return true;
        }
        return false;
    }
   
    bool AgentReturnedVaccine()
    {
        return Vector3.Distance(aiBase.transform.position, plague.transform.position) < distance;
    }

    void OnTriggerEnter(Collider other)
    {
        if (Captured(other))
        {
            Debug.Log("Returning to base");
            ChangeState(doctorState.Return);
        }
    }      
}

I tried adding my attack logic to the update function for it to constantly check if the player is in the appropriate distance to attack but no victory.

You see the agent is supposed to attack the player when in range, with a specified animation set to it, but it doesn't attack the player.

0

There are 0 answers