You are the absolute GOAT. This was everything I wanted regarding the sword swing part of my melee combat system. It feels responsive and flexible, especially when I time the ComboAttackTime (in the Inspector) to just past the DisableWeapon() function in the Animator Window. Thank you so much, I’ll be sure to give you credit for helping me make my game!
For anyone else reading, here is Bixarrio and I’s full PlayerAttackingState script. Feel free to copy and paste.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAttackingState : PlayerBaseState
{
private Attack attack;
private float previousFrameTime;
private bool alreadyAppliedForce;
public PlayerAttackingState(PlayerStateMachine stateMachine, int AttackIndex) : base(stateMachine)
{
attack = stateMachine.Attacks[AttackIndex];
}
public override void Enter()
{
stateMachine.InputReader.AttackDown += HandleAttackDown; //Enables Button Push
stateMachine.Weapon.SetAttack(attack.Damage, attack.Knockback);
stateMachine.Animator.CrossFadeInFixedTime(attack.AnimationName, attack.TransitionDuration);
Debug.Log(attack.AnimationName);
}
public override void Tick(float deltaTime)
{
Move(deltaTime);
FaceTarget();
float normalizedTime = GetNormalizedTime(stateMachine.Animator, "Attack");
if(normalizedTime < 1f)
{
if (normalizedTime >= attack.ForceTime)
{
TryApplyForce();
}
/*if(stateMachine.InputReader.IsAttacking)
{
TryComboAttack(normalizedTime);
} Enables Button Hold*/
}
else
{
if(stateMachine.Targeter.CurrentTarget != null)
{
stateMachine.SwitchState(new PlayerTargetingState(stateMachine));
}
else
{
stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));
}
}
previousFrameTime = normalizedTime;
}
public override void Exit()
{
stateMachine.InputReader.AttackDown -= HandleAttackDown; //Enables Button Push
}
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;
}
void HandleAttackDown()
{
// stateMachine.InputReader.AttackDown -= HandleAttackDown; //Makes it harder to time combos.
// with this enabled, you CANNOT button mash and expect to combo.
float normalizedTime = GetNormalizedTime(stateMachine.Animator, "Attack");
TryComboAttack(normalizedTime);
}//Enables Button Push
}