刚自学Unity,发现Unity 之所以很火,因为很多系统,编辑器,都设计得如此的强大;
大家用起来都比较容易维护。
自学中,发现,一个挺有趣的系统:Animator,这个在Unity 中,有一个独立的子面板,其中,大家如下面:
以上,就是单个动画的状态机可视化管理界面;
any state就是每次都会处理的状态;(任意状态)
idle(闲置状态)
run(跑动状态)
dead(死亡状态)
大家应该也发现了,idle、run、dead这些状态之间都有一些带有方向的线段连接起来;
这些带方向的线段就是:Transition(等会我的代码,会有对应的类),意思就是设置了一些过渡参数,来从,原来的状态,过渡到:指定的状态;
如图:
而每个Transition其实是可以有多个:过渡管道;(Pipeline,有对应的类),就是管理,状态之间可以过渡的参数管理
以上是单个Pipeline,一个Transition中,含多个Pipeline的话,左边的视图中,带方向的的Transition外观会变成:带有三个方向的箭头:
如图:
以上,一个Transition有,两个Pipeline,第一个是当speed>10时(红色线部份),会从:idle过渡到:run状态,
而第二个Pipeline是,hp>50(看绿色线的部份),也会从:idle过渡到:run状态;
多个Pipeline之间的逻辑是:or,运算符:||的关系,意思是:
if (speed > 10 || hp > 50)
// transilated to run
其中,上图中,大家都应该看到了:Condition,speed,Greater,或是hp,Greater这些设置过渡的参数;
对应FSMParam类,这些参数,是存在于单个FSM的,如图:
FSM相关的声明:(注释挺少的,不过代码600多行,我就不贴上来了,有提供百度网盘下载就可以了,往下看)
/// <summary> /// 状态机中,当前状态发生改变的事件委托声明 /// </summary> public delegate void CurStateChangedEventHandler(FSM sender); /// <summary> /// 状态机中,当有参数发生变化时的事件委托声明 /// </summary> public delegate void ParamsChangedEventHandler(FSM sender, ParamsChangedEvent args); /// <summary> /// 过渡参数为函数委托的声明 /// </summary> public delegate bool FSMFuncParamHandler(params object[] objs); /// <summary> /// 状态机中,当有参数发生变化时的参数类声明 /// </summary> public class ParamsChangedEvent : EventArgs; /// <summary> /// 有限状态机 /// ( /// 设计思路,参考:Unity 4.3.2f 版本的Mecanim动画系统中的状态机, /// 根据使用上的功能,来猜想实现思路,当然可能我的实现方式不是最好, /// 如果大家还有比较好的一些见解,那大家一起交流交流吧。 /// 该博文就不多说其它的,我的文采也不好,直接上代码吧。 /// ) /// @author : Jave.Lin(afeng) /// @time : 2014-03-11 /// @version: 1.0 /// </summary> public class FSM; /// <summary> /// 状态 /// </summary> public abstract class State; /// <summary> /// 状态之间的过度处理(可包含多个过度管道) /// </summary> public class Transition; /// <summary> /// 状态之间的过度管道(可包含多个过度条件) /// </summary> public class ChangStatePipeline; /// <summary> /// 过度参数的成立条件类型 /// </summary> [Flags] public enum ConditionType; /// <summary> /// 过度参数类型 /// </summary> public enum FSMParamType; /// <summary> /// 过度参数是函数类型 /// </summary> public class FSMParamFunc : FSMParam; /// <summary> /// 过度参数是值类型 /// </summary> public class FSMParamValue : FSMParam; /// <summary> /// 过度的参数类 /// </summary> public abstract class FSMParam;
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace FSMTestingProject { /// <summary> /// 测试:有限状态机 /// @author : Jave.Lin(afeng) /// @time : 2014-03-11 /// @version: 1.0 /// </summary> class Program { static void Main(string[] args) { Console.ForegroundColor = ConsoleColor.Green; var fsm = new FSM("Jave‘s FSM"); Console.WriteLine(string.Format("Start testing :{0}", fsm)); // add event show cur state changed info fsm.CurStateChangedEvent += (CurStateChangedEventHandler)((sender) => { Console.WriteLine(string.Format("fsm : {0}, had changed cur state, last state : {1}, cur state : {2}", fsm, fsm.LastState, fsm.CurState)); }); // add event show params changed info fsm.ParamsChangedEvent += (ParamsChangedEventHandler)((sender, paramChangedArgs) => { Console.WriteLine(string.Format( "param:{1}, src:{2}, to: {3}", fsm, paramChangedArgs.CurValue.Name, paramChangedArgs.LastValue.Value, paramChangedArgs.CurValue.Value)); }); // add some states fsm.AddState(new MyState(fsm, "idle")); fsm.AddState(new MyState(fsm, "run")); fsm.AddState(new MyState(fsm, "dead")); fsm.AnyState = new MyState(fsm, "any state"); // set cur state fsm.SetCurState(fsm.GetState("idle")); // add fsm some params fsm.AddParam(new FSMParamValue("speed") { Value = 0 }); // init speed = 0; fsm.AddParam(new FSMParamValue("hp") { Value = 100 }); // init hp = 100 // idle state add some transition to run var idleState = fsm.GetState("idle"); var runState = fsm.GetState("run"); if (idleState != null && runState != null) { // create transition var toRunTransition = new Transition(idleState, runState); // create transition pipelines var pipeline = new ChangStatePipeline(idleState, runState); // create pipelines conditions , and add condition var condition = new PipelineCondition(pipeline, "speed", 10, ConditionType.GreaterEquals); pipeline.AddCondition(condition); // transition add pipeline toRunTransition.AddPipeline(pipeline); // at last, state add transition idleState.AddTransition(toRunTransition); } // run back to idle if (idleState != null && runState != null) { // create transition var toRunTransition = new Transition(runState, idleState); // create transition pipelines var pipeline = new ChangStatePipeline(runState, idleState); // create pipelines conditions , and add condition var condition = new PipelineCondition(pipeline, "speed", 10, ConditionType.Less); pipeline.AddCondition(condition); // transition add pipeline toRunTransition.AddPipeline(pipeline); // at last, state add transition runState.AddTransition(toRunTransition); } // idle or run state add some transition to dead state‘s transitions var deadState = fsm.GetState("dead"); if (idleState != null && deadState != null && runState != null) { // idle to dead var trans1 = ToDeadStateTransition(idleState, deadState); idleState.AddTransition(trans1); // run to dead var trans2 = ToDeadStateTransition(runState, deadState); runState.AddTransition(trans2); } //const int updatePerMs = (int)(1f / 60f * 1000); const int updatePerMs = (int)(1000); bool speedAdding = true; // dummy fsm update task var task = Task.Factory.StartNew((Action)(() => { while (true) { fsm.Update(); var speedParam = fsm.GetParam<FSMParamValue>("speed"); if (Convert.ToDouble(speedParam.Value) <= 0) speedAdding = true; else if (Convert.ToDouble(speedParam.Value) > 10) speedAdding = false; fsm.SetParamValue("speed", Convert.ToDouble(speedParam.Value) + (speedAdding ? 1 : -1)); // to run when speed greater and equals 10, back to idle when speed less than 10 var hpParam = fsm.GetParam<FSMParamValue>("hp"); if (Convert.ToDouble(hpParam.Value) > 0) { fsm.SetParamValue("hp", Convert.ToDouble(hpParam.Value) - 5); // minus 10 hp per frame, to dead when hp less and equals 0 } Thread.Sleep(updatePerMs); } })); Console.ReadLine(); } static Transition ToDeadStateTransition(State srcState, State targetState) { var result = new Transition(srcState, targetState); var pipeline = new ChangStatePipeline(srcState, targetState); var condition = new PipelineCondition(pipeline, "hp", 0, ConditionType.LessEquals); pipeline.AddCondition(condition); result.AddPipeline(pipeline); return result; } } class MyState : State { public MyState(FSM fsm, string name) : base(fsm, name) { } public override void EnterState() { Console.WriteLine(string.Format("->Enter State : {0}", Name)); } public override void LeaveState() { Console.WriteLine(string.Format("<-LeaveState : {0}", Name)); } public override void Excute() { Console.WriteLine(string.Format("$$Excute State : {0}", Name)); } } }
项目运行后,可以看到:
先有:idle 的speed一步一步的+1,到speed >= 10时,状态就变成了:run;
然后再有:run,从speed = 11; 变到speed < 10时,状态变成了:idle;
如图:
最后,大家比较关注的:源项目
转载的话,注声明:
转载于:http://blog.csdn.net/linjf520/article/details/21010637
C# FSM (仿Unity 中的Mecanim动画系统的状态机),布布扣,bubuko.com
C# FSM (仿Unity 中的Mecanim动画系统的状态机)
原文:http://blog.csdn.net/linjf520/article/details/21010637