using System; using System.Collections.Generic; namespace SK.Framework { /// /// 状态机 /// public class StateMachine { //状态列表 存储状态机内所有状态 protected readonly List states = new List(); //状态切换条件列表 protected List conditions = new List(); /// /// 状态机名称 /// public string Name { get; set; } /// /// 当前状态 /// public IState CurrentState { get; protected set; } /// /// 添加状态 /// /// 状态 /// 添加成功返回true 否则返回false public bool Add(IState state) { //判断是否已经存在 if (!states.Contains(state)) { //判断是否存在同名状态 if (states.Find(m => m.Name == state.Name) == null) { //存储到列表 states.Add(state); //执行状态初始化事件 state.OnInitialization(); return true; } } return false; } /// /// 添加状态 /// /// 状态类型 /// 状态命名 /// 添加成功返回true 否则返回false public bool Add(string stateName = null) where T : IState, new() { Type type = typeof(T); T t = (T)Activator.CreateInstance(type); t.Name = string.IsNullOrEmpty(stateName) ? type.Name : stateName; return Add(t); } /// /// 移除状态 /// /// 状态 /// 移除成功返回true 否则返回false public bool Remove(IState state) { //判断是否存在 if (states.Contains(state)) { //如果要移除的状态为当前状态 首先执行当前状态退出事件 if (CurrentState == state) { CurrentState.OnExit(); CurrentState = null; } //执行状态终止事件 state.OnTermination(); return states.Remove(state); } return false; } /// /// 移除状态 /// /// 状态名称 /// 移除成功返回true 否则返回false public bool Remove(string stateName) { var targetIndex = states.FindIndex(m => m.Name == stateName); if (targetIndex != -1) { var targetState = states[targetIndex]; if (CurrentState == targetState) { CurrentState.OnExit(); CurrentState = null; } targetState.OnTermination(); return states.Remove(targetState); } return false; } /// /// 移除状态 /// /// 状态类型 /// 移除成返回true 否则返回false public bool Remove() where T : IState { return Remove(typeof(T).Name); } /// /// 切换状态 /// /// 状态 /// 切换成功返回true 否则返回false public bool Switch(IState state) { //如果当前状态已经是切换的目标状态 无需切换 返回false if (CurrentState == state) return false; //当前状态不为空则执行状态退出事件 CurrentState?.OnExit(); //判断切换的目标状态是否存在于列表中 if (!states.Contains(state)) return false; //更新当前状态 CurrentState = state; //更新后 当前状态不为空则执行状态进入事件 CurrentState?.OnEnter(); return true; } /// /// 切换状态 /// /// 状态名称 /// 切换成功返回true 否则返回false public bool Switch(string stateName) { //根据状态名称在列表中查询 var targetState = states.Find(m => m.Name == stateName); return Switch(targetState); } /// /// 切换状态 /// /// 状态类型 /// 切换成返回true 否则返回false public bool Switch() where T : IState { return Switch(typeof(T).Name); } /// /// 切换至下一状态 /// public void Switch2Next() { if (states.Count != 0) { //如果当前状态不为空 则根据当前状态找到下一个状态 if (CurrentState != null) { int index = states.IndexOf(CurrentState); //当前状态的索引值+1后若小于列表中的数量 则下一状态的索引为index+1 //否则表示当前状态已经是列表中的最后一个 下一状态则回到列表中的第一个状态 索引为0 index = index + 1 < states.Count ? index + 1 : 0; IState targetState = states[index]; //首先执行当前状态的退出事件 再更新到下一状态 CurrentState.OnExit(); CurrentState = targetState; } //当前状态为空 则直接进入列表中的第一个状态 else { CurrentState = states[0]; } //执行状态进入事件 CurrentState.OnEnter(); } } /// /// 切换至上一状态 /// public void Switch2Last() { if (states.Count != 0) { //如果当前状态不为空 则根据当前状态找到上一个状态 if (CurrentState != null) { int index = states.IndexOf(CurrentState); //当前状态的索引值-1后若大等于0 则下一状态的索引为index-1 //否则表示当前状态是列表中的第一个 上一状态则回到列表中的最后一个状态 index = index - 1 >= 0 ? index - 1 : states.Count - 1; IState targetState = states[index]; //首先执行当前状态的退出事件 再更新到上一状态 CurrentState.OnExit(); CurrentState = targetState; } //当前状态为空 则直接进入列表中的最后一个状态 else { CurrentState = states[states.Count - 1]; } //执行状态进入事件 CurrentState.OnEnter(); } } /// /// 切换至空状态(退出当前状态) /// public void Switch2Null() { if (CurrentState != null) { CurrentState.OnExit(); CurrentState = null; } } /// /// 获取状态 /// /// 状态类型 /// 状态名称 /// 状态 public T GetState(string stateName) where T : IState { return (T)states.Find(m => m.Name == stateName); } /// /// 获取状态 /// /// 状态类型 /// 状态 public T GetState() where T : IState { return (T)states.Find(m => m.Name == typeof(T).Name); } /// /// 销毁状态机 /// public void Destroy() { FSM.Instance.Destroy(this); } /// /// 状态机刷新事件 /// public void OnUpdate() { //若当前状态不为空 执行状态停留事件 CurrentState?.OnStay(); //检测所有状态切换条件 for (int i = 0; i < conditions.Count; i++) { var condition = conditions[i]; //条件满足 if (condition.predicate.Invoke()) { //源状态名称为空 表示从任意状态切换至目标状态 if (string.IsNullOrEmpty(condition.sourceStateName)) { Switch(condition.targetStateName); } //源状态名称不为空 表示从指定状态切换至目标状态 else { //首先判断当前的状态是否为指定的状态 if (CurrentState.Name == condition.sourceStateName) { Switch(condition.targetStateName); } } } } } /// /// 状态机销毁事件 /// public void OnDestroy() { //执行状态机内所有状态的状态终止事件 for (int i = 0; i < states.Count; i++) { states[i].OnTermination(); } } /// /// 设置状态切换条件 /// /// 切换条件 /// 目标状态名称 /// 状态机 public StateMachine SwitchWhen(Func predicate, string targetStateName) { conditions.Add(new StateSwitchCondition(predicate, null, targetStateName)); return this; } /// /// 设置状态切换条件 /// /// 切换条件 /// 源状态名称 /// 目标状态名称 /// public StateMachine SwitchWhen(Func predicate, string sourceStateName, string targetStateName) { conditions.Add(new StateSwitchCondition(predicate, sourceStateName, targetStateName)); return this; } /// /// 构建状态 /// /// 状态类型 /// 状态名称 /// 状态构建器 public StateBuilder Build(string stateName = null) where T : State, new() { Type type = typeof(T); T t = (T)Activator.CreateInstance(type); t.Name = string.IsNullOrEmpty(stateName) ? type.Name : stateName; if (states.Find(m => m.Name == t.Name) == null) { states.Add(t); } return new StateBuilder(t, this); } /// /// 创建状态机 /// /// 状态机名称 /// 状态机 public static StateMachine Create(string stateMachineName) { return FSM.Instance.Create(stateMachineName); } /// /// 创建状态机 /// /// 状态机类型 /// 状态机名称 /// 状态机 public static T Create(string stateMachineName = null) where T : StateMachine, new() { return FSM.Instance.Create(stateMachineName); } /// /// 销毁状态机 /// /// 状态机名称 /// 销毁成功返回true 否则返回false public static bool Destroy(string stateMachineName) { return FSM.Instance.Destroy(stateMachineName); } /// /// 销毁状态机 /// /// 状态机类型 /// 销毁成功返回true 否则返回false public static bool Destroy() where T : StateMachine { return FSM.Instance.Destroy(typeof(T).Name); } /// /// 获取状态机 /// /// 状态机名称 /// 状态机 public static StateMachine Get(string stateMachineName) { return FSM.Instance.GetMachine(stateMachineName); } /// /// 获取状态机 /// /// 状态机类型 /// 状态机名称 /// 状态机 public static T Get(string stateMachineName) where T : StateMachine { return FSM.Instance.GetMachine(stateMachineName); } /// /// 获取状态机 /// /// 状态机类型 /// 状态机 public static T Get() where T : StateMachine { return FSM.Instance.GetMachine(typeof(T).Name); } } }