Ho’ there!
I’m working on some first-person combat using a State Machine system that operates via a CurrentState Enum and If statements referencing said Enum. It works like this:
function Update () {
if(currentState == CharacterStates.whateverState){
Do State Stuff
}
}
And state changes are handled within each state, giving me control over what you can do and when you can do it:
if(currentState == CharacterStates.whateverState){
if(Input.GetButtonDown("whateverButton"){
currentState = CharacterStates.correspondingState;
}
}
It seemed like a pretty solid system and worked pretty well, until I put in a combo system. The system isn’t operating properly during the combo, which seems impossible based on the programming I’ve done.
This is the code I have for a Three-Strike Combo, without extraneous bits for dodging and such:
function Update () {
if(!canQueue){
attackSlashQueued = false;
}
//IDLE STATE________________________________________________________________________________
if(currentState == CharacterStates.idle){
if(Input.GetButtonDown("Attack")){
currentState = CharacterStates.slash1;
}
}
//SLASH 1 STATE________________________________________________________________________________
if(currentState == CharacterStates.slash1){
animationComponent.Play("Attack_Slash1");
//CANCELS/QUEUES___________________________________________________________________
if(canQueue){
if(Input.GetButtonDown("Attack"))
attackSlashQueued = true;
}
if(canCancel){
if(attackSlashQueued){
currentState = CharacterStates.slash2;
}
}
if(currentAnimationFrame > 2 && animationIsDone){
currentState = CharacterStates.idle;
}
}
//SLASH 2 STATE________________________________________________________________________________
if(currentState == CharacterStates.slash2){
animationComponent.Play("Attack_Slash2");
//CANCELS/QUEUES___________________________________________________________________
if(canQueue){
if(Input.GetButtonDown("Attack"))
attackSlashQueued = true;
}
if(canCancel){
if(attackSlashQueued){
currentState = CharacterStates.slash3;
}
}
if(currentAnimationFrame > 2 && animationIsDone){
currentState = CharacterStates.idle;
}
}
//SLASH 3 STATE________________________________________________________________________________
if(currentState == CharacterStates.slash3){
animationComponent.Play("Attack_Slash3");
//CANCELS/QUEUES___________________________________________________________________
if(canQueue){
if(Input.GetButtonDown("Attack"))
attackSlashQueued = true;
}
if(canCancel){
if(attackSlashQueued){
currentState = CharacterStates.slash2;
}
}
if(currentAnimationFrame > 2 && animationIsDone){
currentState = CharacterStates.idle;
}
}
}
Here’s the breakdown:
-The general state is Idle, where all movement is handled for now.
-If you click the Attack Button in the Idle State, it changes the State to the Slash1 State
-The SlashX States handle the entirety of the attack specifics, like the animation, sounds, and such
-I have toggles baked into the animations that tell the script when you can Queue up an action, and when to execute on that Queued action.
-In theory, if you click the Attack Button in the Slash1 State, it should change the State to the Slash2 State, and it does.
-In the Slash2 State, pressing the Attack Button should change the State to Slash3, and pressing Attack in Slash3 goes back to Slash2, making it an infinite combo.
Here’s the strange part, though: with the current setup, pressing the Attack Button in Slash2 doesn’t make it Slash3, but it replays the Slash2 animation and stays in the Slash2 State until I let it complete, after which is goes back to the Idle State.
I’ve been doing testing with changing the order the States combo in, as well as changing which animation plays in which State, and it looks like the script just refuses to go into the Slash3 State.
It’s super weird- anyone see anything I’m missing?