2024-10-04
框架
00

目录

定义
本质
作用
ProcedureBase
ProcedureManager
编写第一个启动流程
流程切换
流程组件相关属性和函数
扩展:游戏中的流程

定义

贯穿游戏运行时整个生命周期的有限状态机。通过流程,将不同的游戏状态进行解耦将是一个非常好的习惯。对于网络游戏,你可能需要如检查资源流程、更新资源流程、检查服务器列表流程、选择服务器流程、登录服务器流程、创建角色流程等流程,而对于单机游戏,你可能需要在游戏选择菜单流程和游戏实际玩法流程之间做切换。如果想增加流程,只要派生自 ProcedureBase 类并实现自己的流程类即可使用。

本质

  • 单个流程本质上是一个状态,由状态机来进行管理的,我们可以将一个个的流程看作是状态机中的某个状态,切换流程即是切换状态,这样就很好理解了;
  • 流程的执行是线性的,在游戏中的同一时刻只会处于一个流程中,不会同时进行多个流程。

作用

  • 项目从开始到结束,都是由流程来贯穿的。
  • 将业务逻辑划分为一个一个的流程,通过这样的方式,使得项目的逻辑划分更清晰。
  • 如果想要改变整块业务的逻辑执行顺序,切换流程即可。

ProcedureBase

  • ProcedureBase​是所有流程的基类,进入ProcudureBase​查看代码结构,自身继承自FsmState​状态机类,它FsmState的代码几乎一致,拥有一个状态的所有生命周期,是一个状态的完整体现;
csharp
//流程基类。 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​这个关键的函数决定了状态机从哪个流程开始启动

    csharp
    /// <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也提供了一些别的属性和方法,用于得到某个具体的流程以及它的属性信息: ​imageimage

编写第一个启动流程

  • 创建一个Procedure文件夹用于管理流程相关脚本,游戏中的所有流程脚本都存放此处: ​QQ_1727719321201

  • ProcedureLaunch 同样的,继承自ProcedureBase​,此处列出一个流程的所有生命周期函数,它都交给了状态基类来调用,子类来重写,我们可以按需使用它;我们在进入流程的时候输出一段话“游戏流程启动”。

    csharp
    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信息

    QQ_1727720374871

    QQ_1727720534457

  • 注意:

    如果你编写了多个流程,请记住勾选你所需要的,项目中的所有流程都会在Procedure组件中显示出来,只有被勾选的脚本才会执行。 QQ_1727720840980

    如果确认代码无误,但是仍没有输出信息,查看是否开启了GF的日志输出:QQ_1727722660649

流程切换

创建一个新的流程,命名为ProcedureMenu,实现从启动流程 => 菜单流程:

  • QQ_1727721295305
  • 在启动流程进入时,立刻切换到菜单流程: ​QQ_1727721830616
  • 还是不要忘了记得勾选!查看log信息,流程切换成功 ​QQ_1727721978453
  • 通过以上举例,我们已经可以理解流程执行的过程和原理了,当我们需要切换流程时,只需要调用提供的方法ChangeState<T>即可,切换的过程是通过FSM内部执行的,开发者只需要关心流程的自身逻辑和切换的时机。

流程组件相关属性和函数

csharp
//获取当前流程 GameEntry.Procedure.CurrentProcedure; //获取当前流程的持续时间 GameEntry.Procedure.CurrentProcedureTime; //是否存在流程 GameEntry.Procedure.HasProcedure<T>; //获取某个流程 GameEntry.Procedure.GetProcedure<T>;

扩展:游戏中的流程

如下图,是游戏中可能会包含的流程(通过解读StarForce源码得出),我将会在文章的第二个部分会对各个流程进行详细的解释

Procedure.drawio

本文作者:xuxuxuJS

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!