有限状态机

来源:互联网 发布:求生之路2 mac 编辑:程序博客网 时间:2024/06/16 07:56

学习自: 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);    }