Game Framework学习笔记(2):初识流程(Procedure)

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

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

流程介绍

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

有限状态机

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

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

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

流程(Procedure)

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

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

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

流程使用

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

Procedure Component

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

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

01

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

02

到这里就比较好懂了。

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

目前只有一个流程GameFrameworkExample.ProcedureExample

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

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

流程脚本

接着来看流程脚本。

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

这次我们依旧打开它。

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

1
2
3
4
5
6
7
8
9
10
11
12
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。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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

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

03

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

1
2
3
4
5
6
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()中加入一行代码:

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

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

04

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

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

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