设计模式学习之路(九) ------ 有限状态机
程序员文章站
2024-03-19 18:31:34
...
- 理论:http://wiki.unity3d.com/index.php/Finite_State_Machine
实例:
战士AI,使用有限状态机实现
战士有限战斗机状态虚类,后面的状态都要继承于它:
public enum SoldierTransition //转换的条件
{
NullTansition = 0,
SeeEnemy,
NoEnmey,
CanAttack
}
public enum SoldierStateID //状态ID,保证唯一
{
NullState,
Idle,
Chase,
Attack
}
/// <summary>
/// 战士有限战斗机状态虚类,后面的状态都要继承于它
/// </summary>
public abstract class ISoldierState
{
//条件有多个,而字典只需包含当前状态能够转换的状态对应的条件即可
protected Dictionary<SoldierTransition, SoldierStateID> mMap = new Dictionary<SoldierTransition, SoldierStateID>();
protected SoldierStateID mStateID; //唯一,根据ID寻找状态,实例化状态的时候设置
protected ICharacter mCharacter;
protected SoldierFSMSytem mFSM; //状态管理对象
/// <summary>
/// 初始化
/// </summary>
/// <param name="fsm"></param>
/// <param name="character"></param>
public ISoldierState(SoldierFSMSytem fsm,ICharacter character)
{
mFSM = fsm;
mCharacter = character;
}
public SoldierStateID stateID { get { return mStateID; } }
/// <summary>
/// 添加转换条件
/// </summary>
/// <param name="trans"></param>
/// <param name="id"></param>
public void AddTransition(SoldierTransition trans, SoldierStateID id)
{
if (trans == SoldierTransition.NullTansition)
{
Debug.LogError("SoldierState Error: trans不能为空"); return;
}
if (id == SoldierStateID.NullState)
{
Debug.LogError("SoldierState Error: id状态ID不能为空"); return;
}
if (mMap.ContainsKey(trans))
{
Debug.LogError("SoldierState Error: " + trans + " 已经添加上了"); return;
}
mMap.Add(trans, id);
}
/// <summary>
/// 删除转换条件
/// </summary>
/// <param name="trans"></param>
public void DeleteTransition(SoldierTransition trans)
{
if (mMap.ContainsKey(trans) == false)
{
Debug.LogError("删除转换条件的时候, 转换条件:[" + trans + "]不存在"); return;
}
mMap.Remove(trans);
}
//当前字典是否包含转换条件,包含则将ID返回,可以根据这个函数判断条件可以转换成什么状态
public SoldierStateID GetOutPutState(SoldierTransition trans)
{
if (mMap.ContainsKey(trans) == false)
{
return SoldierStateID.NullState;
} else
{
return mMap[trans];
}
}
//进入状态之前要做的事情
public virtual void DoBeforeEntering() { }
//离开状态之前要做的事情
public virtual void DoBeforeLeaving() { }
//Reason Act都是每帧执行
//判断是否需要转换成其他状态
public abstract void Reason( List<ICharacter> targets );
//处理当前状态的操作
public abstract void Act(List<ICharacter> targets);
}
状态机的拥有者,管理状态:
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
/// <summary>
/// 状态机的拥有者,管理状态
/// </summary>
public class SoldierFSMSytem
{
//状态列表
private List<ISoldierState> mStates = new List<ISoldierState>();
private ISoldierState mCurrentState;
//当前状态
public ISoldierState currentState { get { return mCurrentState; } }
//添加状态,每次创建出一个状态都要给FSMSytem进行管理
public void AddState(params ISoldierState[] states)
{
foreach (ISoldierState s in states)
{
AddState(s);
}
}
public void AddState(ISoldierState state)
{
if (state == null)
{
Debug.LogError("要添加的状态为空"); return;
}
if (mStates.Count == 0)
{
mStates.Add(state);
mCurrentState = state;
return;
}
foreach (ISoldierState s in mStates)
{
if (s.stateID == state.stateID)
{
Debug.LogError("要添加的状态ID[" + s.stateID + "]已经添加"); return;
}
}
mStates.Add(state);
}
//删除状态
public void DeleteState(SoldierStateID stateID)
{
if (stateID == SoldierStateID.NullState)
{
Debug.LogError("要删除的状态ID为空" + stateID); return;
}
foreach (ISoldierState s in mStates)
{
if (s.stateID == stateID)
{
mStates.Remove(s);
return;
}
}
Debug.LogError("要删除的StateID不存在集合中:" + stateID);
}
//根据转换条件转换状态,state只要调用这个方法将转换条件传过来即可
public void PerformTransition(SoldierTransition trans)
{
if (trans == SoldierTransition.NullTansition)
{
Debug.LogError("要执行的转换条件为空 : " + trans); return;
}
SoldierStateID nextStateID = mCurrentState.GetOutPutState(trans); //当前状态有没有满足转换条件的状态ID
if (nextStateID == SoldierStateID.NullState)
{
Debug.LogError("在转换条件 [" + trans + "] 下,没有对应的转换状态"); return;
}
//遍历状态列表
foreach (ISoldierState s in mStates)
{
if (s.stateID == nextStateID)
{
mCurrentState.DoBeforeLeaving(); //执行状态离开的函数
mCurrentState = s; //设置当前
mCurrentState.DoBeforeEntering();
return;
}
}
}
}
追逐状态:
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class SoldierChaseState:ISoldierState
{
public SoldierChaseState(SoldierFSMSytem fsm, ICharacter c) : base(fsm, c) { mStateID = SoldierStateID.Chase; }
public override void Reason(List<ICharacter> targets)
{
if (targets == null || targets.Count == 0)
{
mFSM.PerformTransition(SoldierTransition.NoEnmey); return;
}
float distance = Vector3.Distance(targets[0].position, mCharacter.position);
if (distance <= mCharacter.atkRange)
{
mFSM.PerformTransition(SoldierTransition.CanAttack); //转换
}
}
public override void Act(List<ICharacter> targets)
{
//当前状态要做的判断操作
if (targets != null && targets.Count > 0)
{
mCharacter.MoveTo(targets[0].position);
}
}
}
有限状态机控制类:
//有限状态机控制类
public abstract class ISoldier:ICharacter
{
protected SoldierFSMSytem mFSMSystem;//有限状态机管理对象
public ISoldier():base()
{
MakeFSM();
}
//更新状态机
public override void UpdateFSMAI( List<ICharacter> targets )
{
if (mIsKilled) return;
mFSMSystem.currentState.Reason(targets);
mFSMSystem.currentState.Act(targets);
}
/// <summary>
/// 制作状态机,在战士初始化的时候被调用
/// </summary>
private void MakeFSM()
{
mFSMSystem = new SoldierFSMSytem();
SoldierIdleState idleState = new SoldierIdleState(mFSMSystem, this);
idleState.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase);
SoldierChaseState chaseState = new SoldierChaseState(mFSMSystem, this);
chaseState.AddTransition(SoldierTransition.NoEnmey, SoldierStateID.Idle);
chaseState.AddTransition(SoldierTransition.CanAttack, SoldierStateID.Attack);
SoldierAttackState attackState = new SoldierAttackState(mFSMSystem, this);
attackState.AddTransition(SoldierTransition.NoEnmey, SoldierStateID.Idle);
attackState.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase);
mFSMSystem.AddState(idleState,chaseState,attackState);
}
public override void Update()
{
UpdateFSMAI();
}
}
推荐阅读
-
设计模式学习之路(九) ------ 有限状态机
-
观察者模式(Observer) 博客分类: 设计模式学习 publishsubscribeobserver观察者模式设计模式
-
Jive学习心得 博客分类: jive学习 设计模式lucene网络应用数据结构全文检索
-
Javascript设计模式学习笔记(1) 创建类的时候需要注意的一些概念
-
设计模式学习--Singleton泛型类
-
Tomcat6源代码学习(运行源代码及调试) TomcatSVNApacheIDE设计模式
-
Tomcat6源代码学习(运行源代码及调试) TomcatSVNApacheIDE设计模式
-
java设计模式之外观模式学习笔记
-
java设计模式之外观模式学习笔记
-
学习Java设计模式之观察者模式