定义
贯穿游戏运行时整个生命周期的有限状态机。通过流程,将不同的游戏状态进行解耦将是一个非常好的习惯。对于网络游戏,你可能需要如检查资源流程、更新资源流程、检查服务器列表流程、选择服务器流程、登录服务器流程、创建角色流程等流程,而对于单机游戏,你可能需要在游戏选择菜单流程和游戏实际玩法流程之间做切换。如果想增加流程,只要派生自 ProcedureBase 类并实现自己的流程类即可使用。
(官方文档)
本质
- 单个流程本质上是一个状态,由状态机来进行管理的,我们可以将一个个的流程看作是状态机中的某个状态,切换流程即是切换状态,这样就很好理解了;
- 流程的执行是线性的,在游戏中的同一时刻只会处于一个流程中,不会同时进行多个流程。
作用
- 项目从开始到结束,都是由流程来贯穿的。
- 将业务逻辑划分为一个一个的流程,通过这样的方式,使得项目的逻辑划分更清晰。
- 如果想要改变整块业务的逻辑执行顺序,切换流程即可。
ProcedureBase
ProcedureBase
是所有流程的基类,进入ProcudureBase
查看代码结构,自身继承自FsmState
状态机类,它FsmState的代码几乎一致,拥有一个状态的所有生命周期,是一个状态的完整体现;//流程基类。 public abstract class ProcedureBase : FsmState<IProcedureManager> { protected internal override void OnInit(IFsm<IProcedureManager> procedureOwner) { base.OnInit(procedureOwner); } protected internal override void OnEnter(IFsm<IProcedureManager> procedureOwner) { base.OnEnter(procedureOwner); } protected internal override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds) { base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds); } protected internal override void OnLeave(IFsm<IProcedureManager> procedureOwner, bool isShutdown) { base.OnLeave(procedureOwner, isShutdown); } protected internal override void OnDestroy(IFsm<IProcedureManager> procedureOwner) { base.OnDestroy(procedureOwner); } }
ProcedureManager
Manager会在Initialize时创建一个管理流程的状态机以及所有的继承了ProcedureBase的流程,
StartProcedure
这个关键的函数决定了状态机从哪个流程开始启动/// <summary> /// 初始化流程管理器。 /// </summary> /// <param name="fsmManager">有限状态机管理器。</param> /// <param name="procedures">流程管理器包含的流程。</param> public void Initialize(IFsmManager fsmManager, params ProcedureBase[] procedures) { if (fsmManager == null) { throw new GameFrameworkException("FSM manager is invalid."); } m_FsmManager = fsmManager; m_ProcedureFsm = m_FsmManager.CreateFsm(this, procedures); } /// <summary> /// 开始流程。 /// </summary> /// <typeparam name="T">要开始的流程类型。</typeparam> public void StartProcedure<T>() where T : ProcedureBase { if (m_ProcedureFsm == null) { throw new GameFrameworkException("You must initialize procedure first."); } m_ProcedureFsm.Start<T>(); }
- 同时,Manager也提供了一些别的属性和方法,用于得到某个具体的流程以及它的属性信息:
编写第一个启动流程
- 创建一个Procedure文件夹用于管理流程相关脚本,游戏中的所有流程脚本都存放此处:
ProcedureLaunch
同样的,继承自ProcedureBase
,此处列出一个流程的所有生命周期函数,它都交给了状态基类来调用,子类来重写,我们可以按需使用它;我们在进入流程的时候输出一段话“游戏流程启动”。protected internal override void OnInit(IFsm<IProcedureManager> procedureOwner) { base.OnInit(procedureOwner); } protected internal override void OnEnter(IFsm<IProcedureManager> procedureOwner) { base.OnEnter(procedureOwner); } protected internal override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds) { base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds); } protected internal override void OnLeave(IFsm<IProcedureManager> procedureOwner, bool isShutdown) { base.OnLeave(procedureOwner, isShutdown); } protected internal override void OnDestroy(IFsm<IProcedureManager> procedureOwner) { base.OnDestroy(procedureOwner); }
编译后,可以在Proceduer组件中看到启动流程脚本了,勾选它并启动Unity,输出log信息
注意:
如果你编写了多个流程,请记住勾选你所需要的,项目中的所有流程都会在Procedure组件中显示出来,只有被勾选的脚本才会执行。
如果确认代码无误,但是仍没有输出信息,查看是否开启了GF的日志输出:
流程切换
创建一个新的流程,命名为ProcedureMenu,实现从启动流程 => 菜单流程:
-
- 在启动流程进入时,立刻切换到菜单流程:
- 还是不要忘了记得勾选!查看log信息,流程切换成功
- 通过以上举例,我们已经可以理解流程执行的过程和原理了,当我们需要切换流程时,只需要调用提供的方法
ChangeState<T>
即可,切换的过程是通过FSM内部执行的,开发者只需要关心流程的自身逻辑和切换的时机。
流程组件相关属性和函数
//获取当前流程
GameEntry.Procedure.CurrentProcedure;
//获取当前流程的持续时间
GameEntry.Procedure.CurrentProcedureTime;
//是否存在流程
GameEntry.Procedure.HasProcedure<T>;
//获取某个流程
GameEntry.Procedure.GetProcedure<T>;
扩展:游戏中的流程
如下图,是游戏中可能会包含的流程(通过解读StarForce源码得出),我将会在文章的第二个部分会对各个流程进行详细的解释
本文由 xuxuxujs 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。