//-------------------------------------------------- // Motion Framework // Copyright©2018-2020 何冠峰 // Licensed under the MIT license //-------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; namespace MotionFramework.AI { /// /// 有限状态机 /// public class FiniteStateMachine { private readonly List _nodes = new List(); private IFsmNode _curNode; private IFsmNode _preNode; /// /// 节点转换关系图 /// 注意:如果为NULL则不检测转换关系 /// public FsmGraph Graph; /// /// 当前运行的节点名称 /// public string CurrentNodeName { get { return _curNode != null ? _curNode.Name : string.Empty; } } /// /// 之前运行的节点名称 /// public string PreviousNodeName { get { return _preNode != null ? _preNode.Name : string.Empty; } } /// /// 启动状态机 /// /// 入口节点 public void Run(string entryNode) { _curNode = GetNode(entryNode); _preNode = GetNode(entryNode); if (_curNode != null) _curNode.OnEnter(); else MotionLog.Error($"Not found entry node : {entryNode}"); } /// /// 显示帧更新 /// public void Update() { if (_curNode != null) _curNode.OnUpdate(); } /// /// 物理帧更新 /// public void FixedUpdate() { if (_curNode != null) _curNode.OnFixedUpdate(); } /// /// 加入一个节点 /// public void AddNode(IFsmNode node) { if (node == null) throw new ArgumentNullException(); if (_nodes.Contains(node) == false) { _nodes.Add(node); } else { MotionLog.Warning($"Node {node.Name} already existed"); } } /// /// 转换节点 /// public void Transition(string nodeName) { if (string.IsNullOrEmpty(nodeName)) throw new ArgumentNullException(); IFsmNode node = GetNode(nodeName); if (node == null) { MotionLog.Error($"Can not found node {nodeName}"); return; } // 检测转换关系 if (Graph != null) { if (Graph.CanTransition(_curNode.Name, node.Name) == false) { MotionLog.Error($"Can not transition {_curNode} to {node}"); return; } } MotionLog.Log($"FSM transition {_curNode.Name} to {node.Name}"); _preNode = _curNode; _curNode.OnExit(); _curNode = node; _curNode.OnEnter(); } /// /// 返回到之前的节点 /// public void RevertToPreviousNode() { Transition(PreviousNodeName); } /// /// 接收消息 /// public void HandleMessage(object msg) { if (_curNode != null) _curNode.OnHandleMessage(msg); } private bool IsContains(string nodeName) { for (int i = 0; i < _nodes.Count; i++) { if (_nodes[i].Name == nodeName) return true; } return false; } private IFsmNode GetNode(string nodeName) { for (int i = 0; i < _nodes.Count; i++) { if (_nodes[i].Name == nodeName) return _nodes[i]; } return null; } } }