Combo Attack Stuck on Repeat

My issue is similar to “Attacking Force Repeating”. Attack is engaged and the Combo Attack continues to cycle without ever leaving the Attack state.





In the future, please paste the code instead of a screenshot of the code. It is really difficult to help when we have to try and read stuff from a screenshot, and impossible to copy-and-paste code back when we need to. See this post on how to format the code in posts.

At first glance the code looks fine. Have you checked that your animations are tagged with “Attack” and that it is exactly the same, i.e. same spelling, same case, etc?

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

public class PlayerAttackingState : PlayerBaseState
{
    private float previousFrameTime;
    private bool alreadyAppliedForce;
    private Attack attack;

    public PlayerAttackingState(PlayerStateMachine stateMachine, int attackIndex) : base(stateMachine)
    {
        attack = stateMachine.Attacks[attackIndex];
    }

    public override void Enter()
    {
        stateMachine.Animator.CrossFadeInFixedTime(attack.AnimationName, attack.TransitionDuration);
    }

    public override void Tick(float deltaTime)
    {
        Move(deltaTime);
        FaceTarget();
        
        float normalizedTime = GetNormalizedTime();
        if (normalizedTime < 1f) //FLAGGED if (normalizedTime >= previousFrameTime && normalizedTime < 1f)
        {
            if (normalizedTime >= attack.ForceTime)
            {
                TryApplyForce();
            }

            if (stateMachine.InputReader.IsAttacking)
            {
                TryComboAttack(normalizedTime);
            }
        }
        else    ///COMBO ATTACK STATE CHANGE FLAG
        {
            if(stateMachine.Targeter.CurrentTarget != null)
            {
                stateMachine.SwitchState(new PlayerTargetingState(stateMachine));
            }
            else
            {
                stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));
            }
        }
        previousFrameTime = normalizedTime;
    }

    public override void Exit()
    {

    }
    private void TryComboAttack(float normalizedTime)
    {
        if (attack.ComboStateIndex == -1) { return; }
        if (normalizedTime < attack.ComboAttackTime) { return; }
        stateMachine.SwitchState
        (
            new PlayerAttackingState
            (
                stateMachine,
                attack.ComboStateIndex
            )
        );
    }

    private void TryApplyForce()
    {
        if (alreadyAppliedForce) { return; }
        stateMachine.ForceReceiver.AddForce(stateMachine.transform.forward * attack.Force);
        alreadyAppliedForce = true;
    }

    private float GetNormalizedTime() //FLAGGED ANIMATOR REFERENCES
    {
        AnimatorStateInfo currentInfo = stateMachine.Animator.GetCurrentAnimatorStateInfo(0);
        AnimatorStateInfo nextInfo = stateMachine.Animator.GetNextAnimatorStateInfo(0);

        if (stateMachine.Animator.IsInTransition(0) && nextInfo.IsTag("Attack"))
        {
            return nextInfo.normalizedTime;
        }
        else if (!stateMachine.Animator.IsInTransition(0) && currentInfo.IsTag("Attack"))
        {
            return currentInfo.normalizedTime;
        }
        else
        {
            return 0f;
        }
    }
}
---
![attackTag|690x178](upload://vcLZhSkgdcoBsUEHwpU878fxmn7.jpeg)

yes, the “Attack” tag has been applied to all 3 attacks and they are spelled the same.

Looks fine. I just want to make sure; You say the combo continues to cycle. Does that mean it’s doing Attack1, Attack2, Attack3, Attack1, etc. or Attack1, Attack1, Attack1?


Edit
I pasted your code into my own project and it works fine, so whatever you are experiencing is not in the code

Yeah, it’s repeating through Attack1, Attack2, Attack3.
Hmm… okay, no worries. Thx.

It doesn’t make sense that it’s not leaving the attack state. There’s no reason (or code) that will make it just wrap around and start again. Can you show the PlayerTargetingState or PlayerFreeLookState? Whichever one is causing this. Perhaps it finishes the combo and then immediately starts it again

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

public class PlayerFreeLookState : PlayerBaseState
{

    private readonly int FreeLookSpeedHash = Animator.StringToHash("FreeLookSpeed");
    private readonly int FreeLookBlendTreeHash = Animator.StringToHash("FreeLookBlendTree");
    private const float AnimatorDampTime = 0.1f;

    public PlayerFreeLookState(PlayerStateMachine stateMachine) : base(stateMachine){}

    public override void Enter()
    {
        stateMachine.InputReader.TargetEvent += OnTarget;
        stateMachine.Animator.Play(FreeLookBlendTreeHash);
    }

    public override void Tick(float deltaTime)
    {
        if (stateMachine.InputReader.IsAttacking)
        {
            stateMachine.SwitchState(new PlayerAttackingState(stateMachine, 0));
            return;
        }
        
        Vector3 movement = CalculateMovement();
        Move(movement * stateMachine.FreeLookMovementSpeed, deltaTime);

        if (stateMachine.InputReader.MovementValue == Vector2.zero)
        {
            stateMachine.Animator.SetFloat(FreeLookSpeedHash, 0, AnimatorDampTime, deltaTime);
            return;
        }
        stateMachine.Animator.SetFloat(FreeLookSpeedHash, 1, AnimatorDampTime, deltaTime);
        FaceMovementDirection(movement, deltaTime);
    }


    public override void Exit()
    {
        stateMachine.InputReader.TargetEvent -= OnTarget;
    }

    private void OnTarget()
    {
        if (!stateMachine.Targeter.SelectTarget()) { return; }
        stateMachine.SwitchState(new PlayerTargetingState(stateMachine));
    }

    private Vector3 CalculateMovement()
    {
        Vector3 forward = stateMachine.MainCameraTransform.forward;
        Vector3 right = stateMachine.MainCameraTransform.right;
        
        forward.y = 0f;
        right.y = 0f;
        forward.Normalize();
        right.Normalize();

        return forward * stateMachine.InputReader.MovementValue.y +
            right * stateMachine.InputReader.MovementValue.x;
    }

    private void FaceMovementDirection(Vector3 movement, float deltaTime)
    {
        stateMachine.transform.rotation = Quaternion.Lerp(
            stateMachine.transform.rotation,
            Quaternion.LookRotation(movement),
            deltaTime * stateMachine.RotationDamping);
    }

}

using System;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class PlayerTargetingState : PlayerBaseState

{  

    private readonly int TargetingBlendTreeHash = Animator.StringToHash("TargetingBlendTree");

    private readonly int TargetingForwardHash = Animator.StringToHash("TargetingForward");

    private readonly int TargetingRightHash = Animator.StringToHash("TargetingRight");

    public PlayerTargetingState(PlayerStateMachine stateMachine) : base(stateMachine) { }

    public override void Enter()

    {

        stateMachine.InputReader.CancelEvent += OnCancel;

        stateMachine.Animator.Play(TargetingBlendTreeHash);

    }

    public override void Tick(float deltaTime)

    {

        if (stateMachine.InputReader.IsAttacking)

        {

            stateMachine.SwitchState(new PlayerAttackingState(stateMachine, 0));

            return;

        }

        if (stateMachine.Targeter.CurrentTarget == null)

        {

            stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));

            return;

        }

        Vector3 movement = CalculateMovement();

        Move(movement * stateMachine.TargetingMovementSpeed, deltaTime);

        UpdateAnimator(deltaTime);

        FaceTarget();

    }

    public override void Exit()

    {

        stateMachine.InputReader.CancelEvent -= OnCancel;

    }

       

    private void OnCancel()

    {

        stateMachine.Targeter.Cancel();

        stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));

    }

   

    private Vector3 CalculateMovement()

    {

        Vector3 movement = new Vector3();

        movement += stateMachine.transform.right * stateMachine.InputReader.MovementValue.x;

        movement += stateMachine.transform.forward * stateMachine.InputReader.MovementValue.y;

        return movement;

    }

    private void UpdateAnimator(float deltaTime)

    {

        if (stateMachine.InputReader.MovementValue.y == 0)

        {

            stateMachine.Animator.SetFloat(TargetingForwardHash, 0f, 0.1f, deltaTime);

        }

        else

        {

            float value = stateMachine.InputReader.MovementValue.y > 0 ? 1f : -1f;

            stateMachine.Animator.SetFloat(TargetingForwardHash, value, 0.1f, deltaTime);

        }

        if (stateMachine.InputReader.MovementValue.x == 0)

        {

            stateMachine.Animator.SetFloat(TargetingRightHash, 0f, 0.1f, deltaTime);

        }

        else

        {

            float value = stateMachine.InputReader.MovementValue.x > 0 ? 1f : -1f;

            stateMachine.Animator.SetFloat(TargetingRightHash, value, 0.1f, deltaTime);

        }

       

    }

}

maybe something in the “TryComboAttack” method?

OK, So in both cases the attacking state will get to the last attack in the combo and exit the state, but then, on the first frame of the freelook or targeting state, it will immediately start the combo again if the button is still pressed. It works for me because I made a slight modification to the input and stuff; in addition to the IsAttacking boolean, I also fire an event so in my freelook and targeting states, I wait for the event to trigger the attack

Privacy & Terms