有限状态机(英语:finite-state machine,缩写:FSM)
有限状态机又称有限状态自动机(英语:finite-state automation,缩写:FSA),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学计算模型。
简单说,它有三个特征:
- 状态总数(state)是有限的。
- 任一时刻,只处在一种状态之中。
- 某种条件下,会从一种状态转变(transition)到另一种状态。
状态机一般有两种实现方式:
- 使用swith case 来实现,非常简单,这里就不赘述了。
- 使用状态模式实现(本篇文章中心)
状态模式
定义:
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决了两个问题:
- 对象的内部状态更改时,其行为也应更改。
- 特定于状态的行为应该独立定义,也就是说,添加新的状态不应该影响现有状态的行为
状态模式和策略模式非常类似,状态模式与策略模式的区别
类图:
例子:
假如有一款游戏, 一个女英雄他有多种状态, 如站立、下蹲、跳跃、下斩等状态,按照常规的实现方式,我们可以用大量的if else来判断,或者switch case来实现, 但是这样做缺点很明显, 会存在大量bug并且代码不移维护和扩展。
此时我们就可以用状态机(状态模式)来实现,流程图如下:
C#实现(状态模式方式):
//-------------------------------------------------------------------------------------
// TestHeroine.cs
//-------------------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
public class TestHeroine : MonoBehaviour
{
private Heroine _heroine;
void Start ( )
{
_heroine = new Heroine();
}
void Update ( )
{
_heroine.Update();
}
}
英雄类
//-------------------------------------------------------------------------------------
// Heroine.cs
//-------------------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
public class Heroine
{
HeroineBaseState _state;
public Heroine()
{
_state = new StandingState(this);
}
public void SetHeroineState(HeroineBaseState newState)
{
_state = newState;
}
public void HandleInput()
{
}
public void Update()
{
_state.HandleInput();
}
}
状态接口
//-------------------------------------------------------------------------------------
// HeroineBaseState.cs
//-------------------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
public interface HeroineBaseState
{
void Update();
void HandleInput();
}
站立状态
//-------------------------------------------------------------------------------------
// StandingState.cs
//-------------------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
public class StandingState : HeroineBaseState
{
private Heroine _heroine;
public StandingState(Heroine heroine)
{
_heroine = heroine;
Debug.Log("------------------------Heroine in StandingState~!(进入站立状态!)");
}
public void Update()
{
}
public void HandleInput()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
Debug.Log("get KeyCode.UpArrow!");
_heroine.SetHeroineState(new JumpingState(_heroine));
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Debug.Log("get KeyCode.DownArrow!");
_heroine.SetHeroineState(new DuckingState(_heroine));
}
}
}
跳跃状态
//-------------------------------------------------------------------------------------
// JumpState.cs
//-------------------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
public class JumpingState : HeroineBaseState
{
private Heroine _heroine;
public JumpingState(Heroine heroine)
{
_heroine = heroine;
Debug.Log("------------------------Heroine in JumpingState~!(进入跳跃状态!)");
}
public void Update()
{
}
public void HandleInput()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
Debug.Log("get GetKeyDown.UpArrow! but already in Jumping! return!(已经在跳跃状态中!)");
return;
}
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Debug.Log("get KeyCode.DownArrow!");
_heroine.SetHeroineState(new DrivingState(_heroine));
}
}
}
下蹲躲避状态
//-------------------------------------------------------------------------------------
// DuckingState.cs
//-------------------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
public class DuckingState : HeroineBaseState
{
private Heroine _heroine;
public DuckingState(Heroine heroine)
{
_heroine = heroine;
Debug.Log("------------------------Heroine in DuckingState~!(进入下蹲躲避状态!)");
}
public void Update()
{
}
public void HandleInput()
{
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Debug.Log("已经在下蹲躲避状态中!");
return;
}
if (Input.GetKeyUp(KeyCode.UpArrow))
{
Debug.Log("get GetKeyUp.UpArrow!");
_heroine.SetHeroineState(new StandingState(_heroine));
}
}
}
下斩状态
//-------------------------------------------------------------------------------------
// DrivingState.cs
//-------------------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
public class DrivingState : HeroineBaseState
{
private Heroine _heroine;
public DrivingState(Heroine heroine)
{
_heroine = heroine;
Debug.Log("------------------------Heroine in DrivingState~!(进入下斩状态!)");
}
public void Update()
{
}
public void HandleInput()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
Debug.Log("get KeyCode.UpArrow!");
_heroine.SetHeroineState(new StandingState(_heroine));
}
}
}