=====结构=====
1、FSMSystem ---- 状态管理器
/// 状态的增加
/// 状态的删除
/// 状态的修改
/// 状态的查找
2、FSmStateBase - -- 各种状态的基类
人物的各种状态都继承这个类
public class StateAttack : FSMStateBase
public classStateFollow : FSMStateBase
public class StatePatrol : FSMStateBase
3、最后一个
public class FMSController : MonoBehaviour ===控制所有的状态切换
===FSMSysytem===== using UnityEngine; using System.Collections; using System.Collections.Generic; namespace FSM { /// <summary> /// 状态管理器 /// /// 状态的增加 /// 状态的删除 /// 状态的修改 /// 状态的查找 /// </summary> public class FSMSystem { public FSMSystem() { } private List<FSMStateBase> listState = new List<FSMStateBase>();//存储状态的容器 private FSMStateBase curState;//当前状态, public FSMStateBase CurState { get { return curState; } } /// <summary> /// 添加状态 /// </summary> /// <param name="state"></param> public void addState(FSMStateBase state)//基类的引用 { if (state == null) { return; } if (listState.Count == 0)//容器中还没有,准备存第一个状态 { listState.Add(state); curState = state; return; } if (!listState.Contains(state))//保证没有重复的状态 { listState.Add(state); } } /// <summary> /// 删除状态 /// </summary> /// <param name="stateName">状态的名字</param> public void deleteState(string stateName) { if (string.IsNullOrEmpty(stateName)) { return; } for (int i = 0; i < listState.Count; i++) { if (listState[i].Name == stateName) { listState.Remove(listState[i]); //listState.RemoveAt(i); break; } } } /// <summary> /// 转换状态 /// </summary> /// <param name="transition">条件</param> public void doTransition(ETransition transition) { if (transition == ETransition.NULL) { return; } string newStateName=curState.getOutState(transition);//获取当前状态要装换到的下一个状态名字 if (string.IsNullOrEmpty(newStateName)) { return; } //转换状态 for (int i = 0; i < listState.Count; i++) { if (newStateName.Equals(listState[i].Name)) { curState.doBeforeLeaving();//当前状态离开时候要做的事情 curState=listState[i];//更换当前状态 curState.doBeforeEntering();//进入当前状态做的事情 break; } } } } } =====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 string name; //状态的名字 protected float curRotateSpeed = 20;//角速度 protected float curSpeed = 10; //移动速度 protected FSMSystem fms; //状态机管理器 protected Transform transTarget; //追踪的目标 protected Transform transSelf; //自己 public string Name { get { return name; } } //转换条件和状态的名字 protected Dictionary<ETransition, string> map = new Dictionary<ETransition, string>(); //========================================== /// <summary> /// 添加条件 /// </summary> /// <param name="transition"></param> /// <param name="stateName"></param> public void addTransition(ETransition transition, string stateName) { if (transition == ETransition.NULL || string.IsNullOrEmpty(stateName)) { return; } if (!map.ContainsKey(transition)) { map.Add(transition,stateName); } } /// <summary> /// 删除条件 /// </summary> /// <param name="transition"></param> public void deleteTransition(ETransition transition) { if (transition == ETransition.NULL) { return; } if (map.ContainsKey(transition)) { map.Remove(transition); } } /// <summary> /// 旋转当前位置到目标位置 /// </summary> /// <param name="cur"></param> /// <param name="aim"></param> public void rotateTheTarget(Transform cur, Transform aim) { //旋转到目标的位置 Quaternion destRotation; Vector3 relativePos; Vector3 tmpCur; Vector3 tmpAim; tmpCur = cur.position; tmpAim = aim.position; tmpCur.y = 0.0f; tmpAim.y = 0.0f; relativePos = tmpAim - tmpCur; destRotation = Quaternion.LookRotation(relativePos); cur.rotation = Quaternion.Slerp(cur.rotation, destRotation, Time.deltaTime * curRotateSpeed);//插值运算 } /// <summary> /// 获取新的状态,如果有状态过渡 /// </summary> /// <param name="transition"></param> /// <returns></returns> public string getOutState(ETransition transition) { if (map.ContainsKey(transition)) { return map[transition]; } else { return null; } } //进入之前做的事情 public virtual void doBeforeEntering() { } //离开之前做的事情 public virtual void doBeforeLeaving() { } public abstract void action();//控制行为(循环函数Update,控制物体的移动) public abstract void reason();//检测转换(条件检测) } } ======状态控制器==== using UnityEngine; using System.Collections; using FSM; public class FMSController : 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 void Update () { if (fms.CurState!=null) { fms.CurState.action(); fms.CurState.reason(); print("fms.CurState.Name=" + fms.CurState.Name); } } 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); } } ===追击状态 using UnityEngine; using System.Collections; namespace FSM { /// <summary> /// 攻击状态 /// </summary> public class StateAttack : FSMStateBase { CharacterController characterController;//这个组件专门控制角色移动 private float lastFire = -1; private float frequency = 0.1f;//子弹发射频率 public GameObject prefabBullet; public Transform transFirePoint;//发射点 public Transform transFireLight;//发射火光 public Transform[] transBullets; public StateAttack(FSMSystem fms, Transform trans, Transform transFirePoint, Transform transFireLight) { this.fms = fms; this.name = "attack";//状态名字就叫攻击 this.transSelf = trans; transTarget = GameObject.FindGameObjectWithTag("Player").transform; characterController = transSelf.GetComponent<CharacterController>(); this.transFirePoint = transFirePoint; this.transFireLight = transFireLight; prefabBullet = Resources.Load("NewPrefabs/bullet") as GameObject; GameObject goBullet=GameObject.Find("Bullets_Monster1"); if(goBullet!=null) { int num = goBullet.transform.childCount; transBullets=new Transform[num]; int index=0; foreach(Transform t in goBullet.transform) { transBullets[index] = t; index++; } } } public override void action() { rotateTheTarget(transSelf,transTarget); //characterController.Move(transSelf.forward * Time.deltaTime * curSpeed); Animation animation = transSelf.GetComponent<Animation>(); animation.CrossFade("idle");//播放战力开火动画,(老版本动画播放模式) if (Time.time > lastFire + frequency) { transFireLight.gameObject.SetActive(true); lastFire = Time.time; //GameObject curGo = GameObject.Instantiate(prefabBullet, transFirePoint.position, transFirePoint.rotation) as GameObject;//以世界旋转为参考 Transform curBullet = getBullet(); if (curBullet == null) return; curBullet.gameObject.SetActive(true); curBullet.position = transFirePoint.position; curBullet.rotation = transFirePoint.rotation; RaycastHit hitInfo; Bullet b = curBullet.GetComponent<Bullet>(); if (Physics.Raycast(curBullet.position, curBullet.forward, out hitInfo)) { if (b) { b.distanceMove = hitInfo.distance; } //施加力,减少生命,播放音乐 //Vector3 force = transform.forward * 10; //if (hitInfo.rigidbody) //{ // hitInfo.rigidbody.AddForceAtPosition(force, hitInfo.point, ForceMode.Impulse); //} //if (health) //{ // // Apply damage // // health.OnDamage(damagePerSecond / frequency, -spawnPoint.forward); //} } else { if (b) { b.distanceMove = 1000; } } } } public override void reason() { float dis=Vector3.Distance(transSelf.position, transTarget.position); if (dis > 3 && dis < 6)// { fms.doTransition(ETransition.ATTACK_TO_FOLLOW); } else if(dis>6) { fms.doTransition(ETransition.ATTACK_PATROL); } } public Transform getBullet() { for (int i = 0; i < transBullets.Length; i++) { if (!transBullets[i].gameObject.activeInHierarchy) { return transBullets[i]; } } return null; } } } ==巡逻状态 using UnityEngine; using System.Collections; namespace FSM { /// <summary> /// 追踪状态 /// </summary> public class StateFollow : FSMStateBase { CharacterController characterController; public StateFollow(FSMSystem fms, Transform trans) { this.fms = fms; this.name = "follow"; this.transSelf = trans; transTarget = GameObject.FindGameObjectWithTag("Player").transform; characterController = transSelf.GetComponent<CharacterController>(); } public override void action() { Animation animation = transSelf.GetComponent<Animation>(); animation.CrossFade("run_forward"); rotateTheTarget(transSelf,transTarget); characterController.Move(transSelf.forward * Time.deltaTime * curSpeed); //Vector3 moveDirection = transNpc.TransformDirection(Vector3.Cross(Vector3.up, Vector3.left)); //Vector3 velocity = moveDirection.normalized * curSpeed; //if (characterController != null) //{ // characterController.SimpleMove(velocity); //} //播放动画 } public override void reason() { float dis = Vector3.Distance(transSelf.position, transTarget.position); if (dis > 6) { fms.doTransition(ETransition.FOLLOW_TO_PATROL); } else if (dis <= 3)//距离目标3米转到攻击状态 { fms.doTransition(ETransition.FOLLOW_TO_ATTACK); } } } } ===巡逻状态 using UnityEngine; using System.Collections; namespace FSM { /// <summary> /// 巡逻状态 /// </summary> public class StatePatrol : FSMStateBase { private Transform[] points;//巡逻点 private Transform transRandNextPoint;//要巡逻的点(随机获取) CharacterController characterController;//控制器,通过它来移动物体 public StatePatrol(FSMSystem fms, Transform[] points, Transform trans) { this.fms = fms; this.points = points; this.name = "patrol";//当前状态的名字 this.transSelf = trans; this.transTarget = GameObject.FindGameObjectWithTag("Player").transform; characterController = transSelf.GetComponent<CharacterController>(); getNextPoint(); } public void getNextPoint() { if (points != null && points.Length>0) { Transform nextTrans=null; nextTrans = points[Random.Range(0, points.Length)]; while (transRandNextPoint!=null&&transRandNextPoint.Equals(nextTrans)) { nextTrans = points[Random.Range(0, points.Length)]; } transRandNextPoint = nextTrans;//更换不一样的巡逻点 } } /// <summary> /// 执行当前状态的行为 /// </summary> public override void action() { float dis = Vector3.Distance(transSelf.position, transRandNextPoint.position);//计算两个点之间的距离 if (dis < 1) { getNextPoint();//选择下一个巡逻点 } //确定方向 rotateTheTarget(transSelf,transRandNextPoint); //移动 characterController.Move(transSelf.forward * Time.deltaTime * curSpeed); //Vector3 moveDirection = transNpc.TransformDirection(Vector3.Cross(Vector3.up, Vector3.left)); //Vector3 velocity = moveDirection.normalized * curSpeed; //if (characterController != null) //{ // characterController.SimpleMove(velocity); //} //播放动画 Animation animation = transSelf.GetComponent<Animation>(); animation.CrossFade("run_forward"); } public override void reason() { float dis = Vector3.Distance(transTarget.position, transSelf.position); if (dis < 3)//巡逻的时候进入攻击范围 { fms.doTransition(ETransition.PATROL_TO_ATTACK); } else if (dis > 3 && dis < 6) { fms.doTransition(ETransition.PATROL_TO_FOLLOW); } } } }