有限状态机
来源:互联网 发布:求生之路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); }
阅读全文
1 0
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- 有限状态机
- PHP编码规范
- 关于死锁的一些知识点总结
- linux mysql5.7设置root密码
- jquery.cookie用法详细解析
- GBDT(MART) 迭代决策树入门教程
- 有限状态机
- NTP协议
- 广播发送
- MyBatis+MySQL 返回插入的主键ID
- C#调用C++动态库(dll)
- unity3d各平台的路径问题
- GA遗传算法入门到掌握
- WifiP2pSettings工作流程
- java8——lambda expression