状态机管理系统概述
我们玩游戏中经常有这样一种情况:
怪物在平时状态:是一个自己四处反复游走的状态,并不会主动攻击玩家(自动寻路会让怪物自动寻找玩家);
当玩家靠近的时候:怪物开始追随玩家,在一定距离内,玩家走到哪他跟到哪
当靠的特别近的时候:怪物开始攻击玩家;
当玩家加速逃跑:当玩家逃跑到一定的距离的时候,怪物不再追随,回到原来位置继续自己反复游走;
上述描述了一种怪物状态管理的一种系统,叫状态机管理系统,具体思路如下:
1.状态机管理器FSMControl.cs,是整个系统的控制系统,可以控制怪物的当前状态,用于切换怪物当前状态
2.怪物状态分为这么几种情况:自己玩耍状态,追随玩家状态,攻击玩家状态
3.假设怪物有一个基类MonsterBase,该基类记录了怪物的速度,角速度等,还定义了几个虚函数,这几个虚函数分别是 怪物的移动(也可以说是动作) action() 函数和怪物的状态的改变( reaction() 函数)(这是因为假设怪物是自己玩耍状态,那么他的移动就是一个反复的自己happy的移动逻辑;假设怪物要追随了,那么他的移动就是类似自动寻路系统那种的不断跟着玩家的移动逻辑;假设怪物要干你了,那么他就会出招,发射子弹之类的逻辑。)
4.怪物的每个状态我们都把他定义成一个继承实现基类MonsterBase的类的对象,在这个子类里面去实现不同的移动逻辑以及自己的一些逻辑,action() 函数里面记录了怪物是自己玩啊,跟着你啊还是打你啊,reaction() 里面就通过条件(比如玩家是否进入到了攻击范围)重置了MonsterBase基类里面的curbase变量,这个变量就记录了当前的MonsterBase() 是被哪个子类实现的。
5.通过在主程序的update() 函数里面不断调用FSMControl.curbase.action() 和FSMControl.curbase.reaction() 来不断的读当前怪物的状态从而做出相应状态下的怪物的动作逻辑。
(要想理解好该系统,需要好好研究关于抽象函数,虚函数的意义,即实现多态和面向对象的思想)
代码如下:
//FSMController主函数
using UnityEngine;
using System.Collections;
using FSM;
public class FSMController : MonoBehaviour
{
private FSMSystem fms;///FSM系统,用来管理状态
public Transform[] points;//自己玩耍时的四个移动点
public Transform firePoint;//子弹位置
public Transform fireLight;
// Use this for initialization
void Start () {
GameObject curGo = GameObject.FindGameObjectWithTag("PointsPatrol");//
int count=curGo.transform.childCount;
points=new Transform[count];
int index=0;
foreach (Transform a in curGo.transform)
{
points[index] = a;
index++;
}
makeFMS();//状态机系统的初始化
}
// Update is called once per frame
//程序的核心部分,通过多态机制,切换实例化不同的抽象基类的子类,实现调用不同子类中的action和reason方法
void Update () {
if (fms.CurState!=null)
{
fms.CurState.action();
fms.CurState.reason();
}
}
private void makeFMS()
{
fms = new FSMSystem();//状态机管理系统
StatePatrol statePatrol = new StatePatrol(fms, points,transform);//巡逻状态
statePatrol.addTransition(ETransition.PATROL_TO_FOLLOW, "follow");
statePatrol.addTransition(ETransition.PATROL_TO_ATTACK, "attack");
StateFollow stateFollow = new StateFollow(fms, transform);//跟随状态
stateFollow.addTransition(ETransition.FOLLOW_TO_ATTACK, "attack");
stateFollow.addTransition(ETransition.FOLLOW_TO_PATROL, "patrol");
StateAttack stateAttack = new StateAttack(fms, transform, firePoint, fireLight);//攻击状态
stateAttack.addTransition(ETransition.ATTACK_TO_FOLLOW, "follow");
stateAttack.addTransition(ETransition.ATTACK_PATROL, "patrol");
fms.addState(statePatrol);
fms.addState(stateFollow);
fms.addState(stateAttack);
}
}
//FSMStateBase 基类
using UnityEngine;
using System.Collections;
using System.Collections.Generic;//各种集合,数据结构
namespace FSM
{
public enum ETransition//状态机中的连线(转换条件)
{
NULL,//不需要转换
PATROL_TO_FOLLOW,//巡逻到跟随
PATROL_TO_ATTACK,//巡逻到攻击
FOLLOW_TO_ATTACK,//跟随到攻击
FOLLOW_TO_PATROL,//跟随到巡逻
ATTACK_TO_FOLLOW,//攻击到跟随
ATTACK_PATROL,//攻击到巡逻
}
public abstract class FSMStateBase
{
protected float curRotateSpeed = 20;//角速度
protected float curSpeed = 10;//移动速度
protected FSMSystem fms;//状态机管理器
protected Transform transTarget;//追踪的目标
protected Transform transSelf;//自己
protected string name;//状态的名字
public string Name {
get {
return name; } }
protected Dictionary<ETransition, string> map = new Dictionary<ETransition, string>();//装换条件和状态的名字