Game Framework学习笔记的第二篇:流程

流程是贯穿游戏运行时整个生命周期的有限状态机。

流程介绍

在介绍流程之前,我们得先了解什么是有限状态机。

有限状态机

有限状态机,英文缩写FSM(Finite State Machine),其在任意时刻都处于有限状态集合中的某一状态。 这里有两个重点:首先它是离散的,其次他的状态是有限的。

有限状态机是一个非常重要的概念,在计算机领域发挥了巨大的作用。我们在这里也不用过分深究,深究的话整个文章的重点也就跑偏了。简单的举个例子:

比如水果忍者,游戏中水果的状态是有限的,他就是一个有限状态机:它每一帧的变化都是离散的状态的变化。当你的手指切到水果,水果就会感应到被切这个事件,做出相应的响应——被摧毁。

流程(Procedure)

流程是贯穿游戏运行时整个生命周期的有限状态机。

对于网络游戏,你可能需要如检查资源流程、更新资源流程、检查服务器列表流程、选择服务器流程、登录服务器流程、创建角色流程等流程,而对于单机游戏,你可能需要在游戏选择菜单流程和游戏实际玩法流程之间做切换。

这些出自作者的第一篇文档 流程使用手册

流程使用

上面的我们只需要大概明白个概念,就算没明白也不要紧,下面就是如何正式操作。

Procedure Component

首先打开我们之前生成的空项目,并打开之前我们打过的Example场景。

如图,找出场景中GameFramework的子对象Procedure,点击:

在右边的Inspector中,我们可以看到Procedure对象挂载的Procedure Component脚本。

到这里就比较好懂了。

Available Procedures:组件所检测到的流程脚本,会全部列在这里。只要打上对勾,我们就可以在游戏内切换到它了。

目前只有一个流程GameFrameworkExample.ProcedureExample

Entrance Procedure:流程入口,也就是游戏启动后会进入的第一个流程。

同样,目前只有一个流程,当然是GameFrameworkExample.ProcedureExample

流程脚本

接着来看流程脚本。

刚刚从组件里得知,我们现在有且只有一个流程,你应该也能猜到,就是我们上一篇文章打开过的ProcedureExample

这次我们依旧打开它。

打开后,我们来看看ProcedureExample类。

    public class ProcedureExample : ProcedureBase
    {
        protected override void OnEnter(ProcedureOwner procedureOwner)
        {
            base.OnEnter(procedureOwner);

            string welcomeMessage = string.Format("Hello! This is an empty project based on Game Framework {0}.", GameFrameworkEntry.Version);
            Log.Info(welcomeMessage);
            Log.Warning(welcomeMessage);
            Log.Error(welcomeMessage);
        }
    }

如果想增加流程,只要派生自 ProcedureBase 类并实现自己的流程类即可使用。

同样,ProcedureExample类也派生自ProcedureBase,因此能够被Procedure Component识别,在组件里面显示。

根据框架作者的文档,我们新建一个流程ProcedureMain。

using GameFramework.Procedure;
using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;
 
namespace Game
{
    public class ProcedureMain : ProcedureBase
    {
        // 游戏初始化时执行。
        protected override void OnInit(ProcedureOwner procedureOwner)
        {
            base.OnInit(procedureOwner);
        }
 
        // 每次进入这个流程时执行。
        protected override void OnEnter(ProcedureOwner procedureOwner)
        {
            base.OnEnter(procedureOwner);
        }
 
        // 每次轮询执行。
        protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
        }
 
        // 每次离开这个流程时执行。
        protected override void OnLeave(ProcedureOwner procedureOwner, bool isShutdown)
        {
            base.OnLeave(procedureOwner, isShutdown);
        }
 
        // 游戏退出时执行。
        protected override void OnDestroy(ProcedureOwner procedureOwner)
        {
            base.OnDestroy(procedureOwner);
        }
    }
}

上面的代码基本讲清楚了流程类的用法。

根据我的理解,OnInit类似于我们普通的Unity脚本继承的monoBehaviour中的AwakeOnEnter类似于Start,OnUpdate类似于Update

新建好了以后,我们就能在流程插件处看到我们的流程了,勾上对勾就可用了:

接着我们再打开ProcedureExample,修改OnUpdate()方法:

        protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds)
        {
            base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);

            ChangeState<Game.ProcedureMain>(procedureOwner); // 切换流程到 ProcedureMain
        }

ChangeState<Game.ProcedureMain>(procedureOwner);能让我们进入我们刚刚新建的Game.ProcedureMain流程。

为了能够清楚我们到底有没有进入ProcedureMain,我们在ProcedureMain的OnEnter()中加入一行代码:

        protected override void OnEnter(ProcedureOwner procedureOwner)
        {
            base.OnEnter(procedureOwner);
            Log.Debug("进入ProcedureMain!");
        }

接着我们保存代码,返回Unity,点击play按钮。

不出意外的话,就会出现Log信息。

我们成功从GameFrameworkExample.ProcedureExample切换到了Game.ProcedureMain

本篇文章先到此为止,接下来下一篇文章我们会了解下Game Framework的UI机制。


发表评论

电子邮件地址不会被公开。 必填项已用*标注