学习自: http://www.taikr.com/my/course/448 泰课在线 Erick
FSM优势:简单高效 易于扩展 模块化处理
FSMState 抽象类 不继承mono
抽离一些子类共有的东西
例如:巡逻点 移动速度 旋转速度 追逐范围 攻击范围 等等
还有放一个存储转换过程的字典
公有方法:增加状态的方法
删除状态的方法
根据状态返回行为的方法
抽象状态转变的原因
抽象状态转变的行为
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace FSM {
public abstract class FSMState {
/// <summary>
/// 存储转换过程的字典
/// </summary>
protected Dictionary<Transition, FSMActionId> dic = new Dictionary<Transition, FSMActionId>();
protected FSMActionId actionId;
public FSMActionId ActionId { get { return actionId; } }
protected Vector3 destinationPos;// 目标点
protected Transform[] wayPoints;//巡逻点
protected float rotateSpeed;// 旋转速度
protected float moveSpeed;// 移动速度
protected float chaseDistance = 40;// 距离40码追逐
protected float attackDistance = 5;// 距离20码攻击
protected float arriveDistance = 2;// 距离2码到达巡逻点
/// <summary>
/// 往字典里添加状态
/// </summary>
public void AddTransition(Transition trans,FSMActionId actionId) {
if (dic.ContainsKey(trans))
return;
dic.Add(trans, actionId);
//Debug.Log("状态" + trans + "添加成功");
}
/// <summary>
/// 删除
/// </summary>
public void DeleteTransition(Transition trans) {
if (dic.ContainsKey(trans)) {
dic.Remove(trans);
return;
}
}
/// <summary>
/// 根据状态返回行为
/// </summary>
/// <param name="trans"></param>
/// <returns></returns>
public FSMActionId GetOutAction(Transition trans) {
return dic[trans];
}
/// <summary>
/// 寻找下一个寻路点
/// </summary>
public void FindNextPoint() {
int num = Random.Range(0, wayPoints.Length);
Vector3 pos = wayPoints[num].position;
// 如果可以 可以加一个干扰值
Debug.Log(num);
destinationPos = pos;
}
/// <summary>
/// 抽象状态转变的行为
/// </summary>
/// <param name="boss"></param>
/// <param name="player"></param>
public abstract void Act(Transform boss, Transform player);
/// <summary>
/// 抽象状态转变的原因
/// </summary>
/// <param name="boss"></param>
/// <param name="player"></param>
public abstract void Reason(Transform boss, Transform player);
}
}
Patrol
namespace FSM {
/// <summary>
/// 巡逻
/// </summary>
public class Patrol : FSMState
{
/// <summary>
/// 初始化
/// </summary>
public Patrol(Transform[] wp) {
wayPoints = wp;
actionId = FSMActionId.Patrol;
rotateSpeed = 6;
moveSpeed = 80;
FindNextPoint();
}
/// <summary>
/// 巡逻行为中
/// </summary>
/// <param name="boss"></param>
/// <param name="player"></param>
public override void Act(Transform boss, Transform player)
{
Debug.Log(destinationPos);
if (Vector3.Distance(boss.position, destinationPos) < arriveDistance) {
Debug.Log("到达了目标点");
FindNextPoint();//选择下一个目标点
}
// 确定boss方向
Quaternion targetRotation = Quaternion.LookRotation(destinationPos - boss.position);
boss.rotation = Quaternion.Slerp(boss.rotation, targetRotation, Time.deltaTime * rotateSpeed);
// 让角色移动
CharacterController c = boss.GetComponent<CharacterController>();
c.SimpleMove(boss.forward * Time.deltaTime * moveSpeed);
// 播放动画
Animation anim = boss.GetComponent<Animation>();
anim.CrossFade("run");
}
/// <summary>
/// 巡逻状态中
/// </summary>
/// <param name="boss"></param>
/// <param name="player"></param>
public override void Reason(Transform boss, Transform player)
{
if (Vector3.Distance(boss.position, player.position) <= chaseDistance) {
Debug.Log("转换为追逐状态");
boss.GetComponent<AIController>().SetTransition(Transition.SawPlayer);
}
}
}
}
Chase
Attack
Death
继承FSMState
在这些类的构造函数中初始化成员变量
重写状态转变的行为抽象方法:
做具体的事情,播放具体的动画等等
重写状态转变的原因抽象犯法:
达到某种条件转换为某种状态
FSMBase:
public class FSMBase : MonoBehaviour {
protected Transform player;
protected GameObject[] wayPoints;// 寻路点
protected Vector3 distination;// 目的地
// 针对自身框架的方法
protected virtual void Initialize() { }
protected virtual void FSMUpdate() { }
protected virtual void FSMFixedUpdata() { }
void Start () {
Initialize();
}
void Update () {
FSMUpdate();
}
private void FixedUpdate()
{
FSMFixedUpdata();
}
AdavanceFSM:
/// <summary>
/// 状态
/// </summary>
public enum Transition {
SawPlayer,
ReachPlayer,
LostPlayer,
NoHealth
}
/// <summary>
/// 行为
/// </summary>
public enum FSMActionId {
Patrol,
Chase,
Attack,
Dead
}
/// <summary>
/// 管理类
/// </summary>
public class AdavanceFSM : FSMBase
{
private List<FSMState> FSMStates;// 存储所有状态
public FSMActionId CurrentActionId { get; private set; }// 当前行为Id
public FSMState CurrentFSMState { get; private set; } // 当前状态
public AdavanceFSM() {
FSMStates = new List<FSMState>();
}
/// <summary>
/// 向列表中增加状态
/// </summary>
/// <param name="state"></param>
public void AddFSMState(FSMState state) {
if (state == null)
return;
// 状态列表什么都没有
if (FSMStates.Count == 0) {
FSMStates.Add(state);
CurrentFSMState = state;
CurrentActionId = state.ActionId;
return;
}
// 要加入的状态是不是在列表中存在
for (int i = 0; i < FSMStates.Count; i++)
{
if (FSMStates[i].ActionId == state.ActionId) {
return;
}
}
// 如果不存在
FSMStates.Add(state);
}
/// <summary>
/// 删除状态列表中的状态
/// </summary>
/// <param name="state"></param>
public void DeleteFSMState(FSMActionId fsmState) {
foreach (FSMState state in FSMStates)
{
if (state.ActionId == fsmState) {
FSMStates.Remove(state);
return;
}
}
Debug.Log("当前列表中不存在这个状态");
}
/// <summary>
/// 转变状态
/// </summary>
/// <param name="trans"></param>
public void PerformTransition(Transition trans) {
FSMActionId id = CurrentFSMState.GetOutAction(trans);
CurrentActionId = id;
for (int i = 0; i < FSMStates.Count; i++)
{
if (FSMStates[i].ActionId == CurrentActionId) {
CurrentFSMState = FSMStates[i];
break;
}
}
}
AIController:
挂载在游戏对象身上
public class AIController : AdavanceFSM
{
/// <summary>
/// 初始化
/// </summary>
protected override void Initialize()
{
player = GameObject.FindGameObjectWithTag("Player").gameObject.transform;
ConstructFSM();
}
private void ConstructFSM()
{
// 进行路点初始化
wayPoints = GameObject.FindGameObjectsWithTag("Point");
for (int i = 0; i < wayPointsTranform.Length; i++)
{
wayPointsTranform[i] = wayPoints[i].transform;
}
// 针对每一个行为进行初始化 针对每个行为进行状态到行为转变的添加
Patrol patrol = new Patrol(wayPointsTranform);
patrol.AddTransition(Transition.SawPlayer, FSMActionId.Chase);
patrol.AddTransition(Transition.NoHealth, FSMActionId.Dead);
Chase chase = new Chase(wayPointsTranform);
chase.AddTransition(Transition.ReachPlayer, FSMActionId.Attack);
chase.AddTransition(Transition.LostPlayer, FSMActionId.Patrol);
Attack attack = new Attack(wayPointsTranform);
attack.AddTransition(Transition.SawPlayer, FSMActionId.Chase);
attack.AddTransition(Transition.LostPlayer, FSMActionId.Patrol);
attack.AddTransition(Transition.NoHealth, FSMActionId.Dead);
Dead dead = new Dead();
// 把状态列表进行初始化
AddFSMState(patrol);
AddFSMState(chase);
AddFSMState(attack);
AddFSMState(dead);
}
protected override void FSMUpdate()
{
protected override void FSMFixedUpdata()
{
CurrentFSMState.Reason(transform, player.transform);
CurrentFSMState.Act(transform, player.transform);
}
/// <summary>
/// 设置状态
/// </summary>
/// <param name="trans"></param>
public void SetTransition(Transition trans)
{
PerformTransition(trans);
}