Issue with attacking and animation in a 2D game

So I’m working on a basic platformer with attack mechanics similar to Wonderboy, and I’m having trouble performing a basic melee attack.

The way I have it set up is with an abstract behaviour class that all my behaviours extend, an input state class to detect how long buttons have been held down etc, and a player manager to manage animation states.

My issue is that I want the animation to play once when the attack button is pressed, and I want attack to be disabled as longa s the button is held down so the player can’t simply hold down the attack button and keep on attacking. However just when I thought I got this working, the player actually cuts out of the 6-frames sword swing animation after the first or second frame. I’ll paste the code from those three classes below and I really hope you guys can help me out.

My Attack class:

using UnityEngine;
using System.Collections;

public class Attack : AbstractBehaviour {

    public bool attacking = false;


    private Duck duckState;
    private Animator anim;

    protected override void Awake()
    {
        base.Awake();

        duckState = GetComponent<Duck> ();
        anim = GetComponent<Animator> ();
    }

    // Use this for initialization
    void Start () {
	
	}
	
	// Update is called once per frame
	protected virtual void Update () {

        var canAttack = inputState.GetButtonValue(inputButtons[0]);
        //var holdTime = inputState.GetButtonHoldTime(inputButtons[0]);
        
        if (canAttack)
        {
            OnAttack(true);
        }
        else
        {
            OnAttack(false);
        }
    }

    protected virtual void OnAttack(bool value)
    {
        attacking = value;

        if (!duckState.ducking)
        {
            ToggleScripts(!attacking);
        }
        
    }
}

My Player Manager:

using UnityEngine;
using System.Collections;

public class PlayerManager : MonoBehaviour {

    private InputState inputState;
    private Walk walkBehaviour;
    private Animator animator;
    private CollisionState collisionState;
    private Duck duckBehaviour;
    private Attack attackBehaviour;

    void Awake()
    {
        inputState = GetComponent<InputState> ();
        walkBehaviour = GetComponent<Walk> ();
        animator = GetComponent<Animator> ();
        collisionState = GetComponent<CollisionState> ();
        duckBehaviour = GetComponent<Duck> ();
        attackBehaviour = GetComponent<Attack> ();
    }

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
        if (collisionState.standing)
        {
            ChangeAnimationState(0);
        }

        if (inputState.absVelX > 0)
        {
            ChangeAnimationState(1);
        }

        if(inputState.absVelY > 0)
        {
            ChangeAnimationState(2);
        }
        if (duckBehaviour.ducking)
        {
            ChangeAnimationState(3);
        }
        if (attackBehaviour.attacking)
        {
            if (!duckBehaviour.ducking)
            {
                ChangeAnimationState(4);
            }
            else
            {
                ChangeAnimationState(5);
            }
        }
    }

    void ChangeAnimationState(int value)
    {
        animator.SetInteger("AnimState", value);
    }
}

My Input State manager:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ButtonState
{
    public bool value;
    public float holdTime = 0f;
}

public enum Directions
{
    Right = 1,
    Left = -1
}

public class InputState : MonoBehaviour {

    public Directions direction = Directions.Right;
    public float absVelX = 0f;
    public float absVelY = 0f;

    private Rigidbody2D body2d;
    private Dictionary<Buttons, ButtonState> buttonStates = new Dictionary<Buttons, ButtonState>();

    void Awake()
    {
        body2d = GetComponent<Rigidbody2D> ();
    }

    void FixedUpdate()
    {
        absVelX = Mathf.Abs(body2d.velocity.x);
        absVelY = Mathf.Abs(body2d.velocity.y);
    }

    public void SetButtonValue(Buttons key, bool value)
    {
        if (!buttonStates.ContainsKey(key))
            buttonStates.Add(key, new ButtonState());

        var state = buttonStates[key];

        if (state.value && !value)
        {
            Debug.Log("Button " + key + " released after " + state.holdTime);
            state.holdTime = 0f;
        }else if (state.value && value)
        {
            state.holdTime += Time.deltaTime;
            Debug.Log("Button " + key + " down for" + state.holdTime);
        }


        state.value = value;
    }

    public bool GetButtonValue(Buttons key)
    {
        if (buttonStates.ContainsKey(key))
            return buttonStates [key].value;
        else
            return false;
    }

    public float GetButtonHoldTime(Buttons key)
    {
        if (buttonStates.ContainsKey(key))
            return buttonStates[key].holdTime;
        else
            return 0;
    }

}

I really hope you guys can help, I’ve been tackling this issue for the past six hours and haven’t worked it out completely. I just want the animation to play once through the entire clip of 6 frames, preferably without using that reference I put in to the animator because I’m sure there’s a better way to do it, as I’d rather have it depend on the AnimState I’ve set in the animation controller because I’m going to have different sprites for different equipment on my main character and I’d rather it be dependent on a variable like that to keep things simple.

EDIT: I’ll also include this class since my behaviours extend it.

AbstractBehaviour:

using UnityEngine;
using System.Collections;

public abstract class AbstractBehaviour : MonoBehaviour {

    public Buttons[] inputButtons;
    public MonoBehaviour[] disableScripts;

    protected InputState inputState;
    protected Rigidbody2D body2d;
    protected CollisionState collisionState;

    protected virtual void Awake()
    {
        inputState = GetComponent<InputState> ();
        body2d = GetComponent<Rigidbody2D> ();
        collisionState = GetComponent<CollisionState> ();
    }
    
    protected virtual void ToggleScripts (bool value)
    {
        foreach (var scripts in disableScripts)
        {
            scripts.enabled = value;
        }
    }

}

Alright so I actually figured this out the next day, and I know it’s not very complicated but I’ll leave the solution here in case of the off-chance that someone else has this problem.

I ended up adding an EndAttack() method in my attack class which gets called during the last frame of my attack animation. All it does is set the “attacking” variable to false. I wanted to avoid using animation events if I could but since it’s working 100% of the time even on fast speed I guess I’ll use it unless any further problem arise.