Behavioral Design Pattern
State
Armando García Morán
Problem Escenario
Playable Character
Idle
Walk
Jump
class Player
Update()
if InputRight
moveRight()
animWalkingRight()
else if InputLeft
moveLeft()
animWalkingLeft()
else
animIdle()
Walk
class Player
Update()
if InputRight
moveRight()
animWalkingRight()
else if InputLeft
moveLeft()
animWalkingLeft()
else if InputUp
moveUp()
animJumping()
else
animIdle()
Jump
Ilimited Jump ?
Constrained Jump
Standing State > Jumping State
Jumping State > Jumping State
class Player
enum states{ Standing, Jumping }
currentState = states.Standing;
Update()
if InputRight
moveRight()
if currentState == states.Standing
animWalkingRight()
else animJumping()
else if InputLeft
moveLeft()
if currentState == states.Standing
animWalkingLeft()
else animJumping()
else if InputUp && currentState == states.Standing
moveUp()
animJumping()
else
animIdle()
onGroundHit()
currentState = states.Standing;
onGroundLeave()
currentState = states.Jumping;
Jump
class Player
enum states{ Standing, Jumping, Dead }
currentState = states.Standing;
Update()
if currentState != states.Dead
if InputRight
moveRight()
if currentState == states.Standing
animWalkingRight()
else animJumping()
else if InputLeft
moveLeft()
if currentState == states.Standing
animWalkingLeft()
else animJumping()
else if InputUp && currentState == states.Standing
moveUp()
animJumping()
else
animIdle()
onGroundHit()
currentState = states.Standing
onGroundLeave()
currentState = states.Jumping
onHit()
animDead()
currentState = states.Dead
Dead
class Player
enum states{ Standing, Jumping, Dead, Crouching }
currentState = states.Standing;
Update()
if currentState != Dead
if InputRight
moveRight()
if currentState == states.Standing
animWalkingRight()
if currentState == states.Crouching
animWalkingCrouchedRight()
else animJumping()
else if InputLeft
moveLeft()
if currentState == states.Standing
animWalkingLeft()
if currentState == states.Crouching
animWalkingCrouchedLeft()
else animJumping()
else if InputUp &&
( currentState == states.Standing || currentState == states.Crouching )
moveUp()
animJumping()
else if InputDown
if currentState == states.Standing
currentState = states.Crouching
if currentState == states.Standing || currentState == states.Crouching
animCrouching()
else
animIdle()
onGroundHit()
currentState = states.Standing;
onGroundLeave()
currentState = states.Jumping;
onHit()
currentState = states.Dead;
What if I press UP and DOWN at the same time?
This is becoming so messy and we're not even halfway !
State Design Pattern
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
Behavior
States
- Standing
- Jumping
- Dead
- Crouching
Intent
Standing
Dead
Crouching
Jumping
Player
PlayerState
PlayerJumping
PlayerStanding
public interface IPlayerState{
void Up();
void Down();
void Left();
void Right();
void UpRight();
void UpLeft();
void DownRight();
void DownLeft();
void None();
string GetAnimationName ();
}
PlayerState
PlayerIdle - IdleState
public class PlayerIdle : IPlayerState{
...
public static IPlayerState GetInstance(Player player){...}
public override void Right(){
player.MoveRight ();
player.SetState ( PlayerWalking.GetInstance(player) );
}
public override void Left(){...}
public override void Up(){
player.Jump ();
player.SetState ( PlayerJumping.GetInstance(player) );
}
public override void UpRight(){...}
public override void UpLeft(){...}
public override void Down(){
player.SetState ( PlayerCrouched.GetInstance(player) );
}
public override void DownRight(){
player.MoveRight ();
player.SetState ( PlayerWalkingCrouched.GetInstance(player) );
}
public override void DownLeft(){...}
public override void None(){}
}
public class Player : MonoBehaviour {
private IPlayerState currentState ;
...
void FixedUpdate () {
bool up = Input.GetKey (KeyCode.UpArrow);
bool down = Input.GetKey (KeyCode.DownArrow);
bool left = Input.GetKey (KeyCode.LeftArrow);
bool right = Input.GetKey (KeyCode.RightArrow);
if ( up && !down && !left && !right ) currentState.Up();
else if ( up && !down && left && !right ) currentState.UpLeft();
else if ( up && !down && !left && right ) currentState.UpRight();
else if ( !up && down && !left && !right ) currentState.Down();
else if ( !up && down && left && !right ) currentState.DownLeft();
else if ( !up && down && !left && right ) currentState.DownRight();
else if ( !up && !down && !left && right ) currentState.Right();
else if ( !up && !down && left && !right ) currentState.Left();
else currentState.None();
}
public void SetState(IPlayerState newState){
if (currentState != newState) {
currentState = newState;
...
}
}
void Update(){
...
animator.SetTrigger( currentState.GetAnimationName() );
...
}
public void Jump(){...}
public void MoveRight(){...}
public void MoveLeft(){...}
...
}
Player
Can you finish the rest of the states?
State - Design Patterns
By Armando Garcia
State - Design Patterns
- 595