Unity GameFramework丨(二)流程

it2023-12-02  74

大家好,我是SKODE。

小提示:选中左侧目录,可快速找到所需内容

本系列博客地址:传送门

E大该章链接:传送门

 

一、什么是流程

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

项目从打开,到关闭这一条线,就是由一个个流程连起来的。这一条线是断不了的。如果要进行别的功能,切换流程就好了。

一个流程就像是一个单独的模块,有生命周期,数据等等。它就是一个继承了 ProcedureBase 的脚本。

UGF框架管着当前流程,管着切换流程。下方方法,就完成了切换流程。

//使用 ChangeState API切换流程 ChangeState<我们的流程脚本>(procedureOwner);

 

 

二、流程有什么作用?

比如说如下图所示:

该图上每一个Procedure xxx都是一个流程脚本。

 

ProcedureLaunch流程负责将版本信息以json文本的形式写到这个游戏文件中、配置这个游戏的语言、声音等等。

ProcedureSplash流程负责切换这个游戏为单机模式、联网更新模式,或者是Unity编辑器模式。

ProcedurePreload流程负责加载我们写的配置表、UI使用到的字体等等。

ProcedureChangeScene流程负责切换场景,在切换场景时关闭所有声音、还原游戏速度、隐藏所有我们实例化的物体,最后切换场景,播放对应场景的声音,切换到该场景的初始流程。

ProcedureMain流程是我自己项目中写的一个流程了,因为我刚切换完场景就进入了这个流程,那么我可以在这个流程的初始化生命周期中打开我想打开的东西、实例化我想实例化的实体、并且可以提供方法,让打开的UI去调用,当达到一定条件时切换到别的流程,比如游戏胜利流程。

 

 

三、流程的生命周期

流程是有自己的生命周期,且每一个都有!只要你继承ProcedureBase,你的脚本就是一个流程脚本。

你可以将单独的UI模块做成一个流程,单独的功能做成一个流程,这样就不至于很多代码挤在一个脚本中,避免代码在整个项目中相互调用。

 

我们可以看看一个流程的生命周期:

using GameFramework.Procedure; using UnityGameFramework.Runtime; using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>; public class Demo2_ProcedureMenu : ProcedureBase { protected override void OnInit(ProcedureOwner procedureOwner) { base.OnInit(procedureOwner); } protected override void OnEnter(ProcedureOwner procedureOwner) { base.OnEnter(procedureOwner); Log.Debug("进入菜单流程,可以在这里加载菜单UI。"); } 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); } }

 

现在我们明白了:

UGF控制着当前用哪一个流程这个流程执行着生命周期函数,所以可以完成我们的逻辑。UGF通过切换流程,完成功能的切换

 

 

四、怎样使用流程

1、编写流程

下面脚本示例了一个:从框架启动流程,切换到登陆的菜单流程(Menu菜单)。

框架启动流程:

using GameFramework.Procedure; using UnityGameFramework.Runtime; using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>; public class Demo2_ProcedureLaunch : ProcedureBase { protected override void OnEnter(ProcedureOwner procedureOwner) { base.OnEnter(procedureOwner); //得到框架场景组件 SceneComponent sceneComponent = GameEntry.GetComponent<SceneComponent>(); // 切换场景 sceneComponent.LoadScene("Assets/Demo2/Demo2_Menu.unity", this); // 切换流程 ChangeState<Demo2_ProcedureMenu>(procedureOwner); } }

 

菜单流程:

using GameFramework.Procedure; using UnityGameFramework.Runtime; using ProcedureOwner = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>; public class Demo2_ProcedureMenu : ProcedureBase { protected override void OnEnter(ProcedureOwner procedureOwner) { base.OnEnter(procedureOwner); Log.Debug("进入菜单流程,可以在这里加载菜单UI。"); } }

 

2、将流程配置到框架

勾选你想要运行的流程

下方选择第一个要运行的流程

 

3、配置场景及文件

在Assets/Demo2下,新建Demo2_Menu的场景,并将场景添加进BuildSettings。

 

然后运行,现在面板上是否出现了新场景呢?

 

该处案例只是一个最基础的案例,至于我们想要卸载之前场景,进入新场景,那是在切换场景流程中实现的。

大家可参考《StarForce》的ProcedureChangeScene流程。

 

 

五、案例:UI怎样切换流程

该案例可等你学完UI章节后再来观看。

 

在《StarForce》中,流程的控制(切换)全部是写在继承了 ProcedureBase 的脚本中的,在其他地方(比如继承了 UIFormLogic 的UI逻辑中)不会写。

这样的好处是做到了集中管理,什么样的东西在什么地方,方便我们查找代码。

 

那比如说我们在UI中或者实体中,一个属性值变了(比如控制的角色升级、被消灭了),想切换流程,该怎样操作呢?

是这样的:

 

1、在流程脚本中写切换流程的方法

下方脚本为示例:

public class ProcedureMenu : ProcedureBase { private bool m_StartGame = false; public void StartGame() { m_StartGame = true; } protected override void OnEnter(ProcedureOwner procedureOwner) { base.OnEnter(procedureOwner); m_StartGame = false; } protected override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds) { base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds); if (m_StartGame) { procedureOwner.SetData<VarInt32>("NextSceneId", GameEntry.Config.GetInt("Scene.Main")); procedureOwner.SetData<VarByte>("GameMode", (byte) GameMode.Survival); ChangeState<ProcedureChangeScene>(procedureOwner); } } }

 

2、在UI中写调用本流程中切换流程的方法

打开UI时先获取本流程

接着就可以获取该流程中的方法了。

public class MenuForm : UGuiForm { private ProcedureMenu m_ProcedureMenu = null; public void OnStartButtonClick() { m_ProcedureMenu.StartGame(); } protected override void OnOpen(object userData) { base.OnOpen(userData); m_ProcedureMenu = (ProcedureMenu) userData; } }

 

 

六、案例:流程怎样获得UI逻辑

该案例可等你学完UI章节后再来观看。

 

我们在一个流程里面打开了某UI界面,那想在这个流程里,打开该UI后对该UI进行初始化, 该怎样做呢?

这儿的这个UI逻辑,是指我们给UI写的继承了 UIFormLogic 的UI脚本。

public class ProcedureMenu : ProcedureBase { // 你的UI逻辑 private MenuForm m_MenuForm = null; protected override void OnEnter(ProcedureOwner procedureOwner) { base.OnEnter(procedureOwner); GameEntry.Event.Subscribe(OpenUIFormSuccessEventArgs.EventId, OnOpenUIFormSuccess); GameEntry.UI.OpenUIForm(UIFormId.MenuForm, this); } private void OnOpenUIFormSuccess(object sender, GameEventArgs e) { OpenUIFormSuccessEventArgs ne = (OpenUIFormSuccessEventArgs) e; if (ne.UserData != this) return; // MenuForm 为你给该界面写的UI逻辑,(回忆提示:它继承了UGuiForm或者UIFormLogic) m_MenuForm = (MenuForm) ne.UIForm.Logic; } }

 

 

七:流程怎样调用其他流程中的逻辑

目标:从A流程,切换到B流程,并且想在切换完成后,在A流程里调用B流程里的方法。

本来想实现这个目标,认为A流程已经切换到B流程了,已经执行完了,怎么还能调用?

但测试发现绝了,UGF竟然很轻松的实现了这个目标

 

方法:

首先获取到下个流程接着切换流程最后直接调用下个流程里的方法即可。 protected override void OnUpdate(IFsm<IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds) { base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds); if (m_ChangeMenu) { procedureOwner.SetData<VarInt>(Constant.Delivery.ChangeMenu, m_MenuId); ChangeState<ProcedureFileControl>(procedureOwner); ProcedureFileControl pro = (ProcedureFileControl) GameEntry.Procedure.CurrentProcedure; pro.RefreshMenu(); } }

 

获取流程的方法:

// 使用泛型参数获取流程 ProcedureBase procedure1 = procedureComponent.GetProcedure<ProcedureLaunch>(); // 使用类型参数获取流程 ProcedureBase procedure2 = procedureComponent.GetProcedure(typeof(ProcedureLaunch));

 

 

一起进步

我是SKODE

我是橙子va 认证博客专家 XR博主 前端框架 U3D开发者,AR/MR研究方向。有过联想VR项目开发、影创MR开发,也在杭电当过讲师,给网易AR上架过项目。是国内某知名电影及电视剧观众。个人联系方式:skode@foxmail.com
最新回复(0)