微软交流社区

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 149|回复: 0

【UE5】非表结构数据驱动(一):Flow Graph

[复制链接]

1

主题

2

帖子

3

积分

新手上路

Rank: 1

积分
3
发表于 2023-1-24 01:04:40 | 显示全部楼层 |阅读模式
一般情况下,我们在UE里使用数据驱动,往往会使用Data Table, Data Asset,Composite Datatable,本文致力于向大家介绍一些非典型的/非表结构的数据驱动方式,他们在使用的时候各有利弊,希望能够帮助大家在开发中选用符合自己心意的结构。
哥们儿开始游戏开发生涯是从给游戏做MOD开始的,因此对RA2等游戏的编辑器情有独钟,在个人看来,如果一个项目的框架足够成熟,那么内容填充如果依然需要大量书写新代码的话,那项目的数据驱动就不算做到位。在大型的团队项目开发中,为了工作流方便,一般会尽量使用Excel等,但在我个人开发时,我会尽量避免使用Excel,一方面为了充分利用引擎内表格编辑器对引用管理的便捷性,另一方面则是引擎内编辑器对非表结构数据的支持。
工具给你,别杀我程序兄弟了!
对于一些数据结构而言,表结构并不是最佳表示。例如,一个多分支的对话,一个含有条件判断与Gameplay逻辑的Buff,一个类似于GTA一样的任务系统等,在本文,我们介绍一种思路:Flow Graph。
Flow Graph旨在解决对话,任务,叙事等多项任务,并有能力替换掉难以管理的关卡蓝图。Flow Graph的作者曾在《巫师3:狂猎》项目组中工作,因为想念巫师3的编辑器而开发了此插件,其Github链接如下:
接下来,我们来正式的介绍Flow Graph
<hr/>一. 入门简介

一张Flow Graph看起来如下图:



Flow Graph示例

看起来非常像蓝图对吧,不同的是,蓝图里每一个Node代表的是一个函数,而Flow Graph中的每个Node代表的是一个UObject,他的变量会在细节面板上公开,这样允许使用者很容易的使用它来指定数据。Node可以是蓝图风格的依次执行,但Flow Graph的强大之处在于Node可以是Latent的,这意味着图可以“暂停”来等待某个事件将其激活,或者等待一个异步函数运行完成后继续执行。
同时,由于蓝图是函数性质的,同一个函数,不可能有两个节点同时在运行,但Flow Graph可以,Flow Graph同一时刻可能有多个节点处于激活状态。这允许我们轻而易举的实现某些Gameplay功能,例如,GTA的赛车任务可能会要求我们在3分钟之内完成某项任务,否则视为任务失败:



实际开发中,使用你自己的实现代替这些仅用来表意的节点

Sequence的第一条可以根据你的项目和你设计的节点来实现,比如等待玩家上车->玩家依次通过检查点->到达终点->任务完成等,正如我上面所说的,节点可以通过监听信号的方式来决定何时触发Output,因此这些都很简单。一旦任务开始,上下两条逻辑实际在同时执行,这就是Flow Graph带给我的自信。
二. 使用Flow Graph

Flow Graph为我们在Content Browser中提供两种新类型的Asset,分别为Flow Asset与Flow Node Blueprint


Flow Asset代表一张可以编辑的图,而Flow Node Blueprint则代表单个的节点。我们新建一个Flow Node Blueprint,大体的看一眼它提供的接口。


对于有经验的朋友们,看到这张图就已经可以估计它的使用了,对于每一个节点,执行的时候就触发Execute Input,结束运行则触发Cleanup,顾名思义即可。触发下一个节点使用Trigger Output函数,通过Pin Name来触发,这很灵活,因为一个节点的输入和输出个数都是可变的,在很多情况下,你需要通过节点的名称来控制触发逻辑。甚至,如果你愿意,你也可以不由节点来触发Output,比如一个对话的选项,由UI的回调事件来触发Output。


Flow Graph还提供了FlowComponent和FlowSubsystem,FlowComponent用于实现Actor与Flow Graph的交互,我们在下一小节展开细说,FlowSubsystem则作为全局单例,提供了很多好用的接口,如获取一个Actor正在激活的所有Flow Graph,获取某个特定的Flow Graph,开始或结束一个FlowGraph等



Flow Component

三. Actor与Flow Graph的通信

前文中,我大量的讲述Flow Graph可以监听信号,那么他到底怎么监听呢?实际上,这里的实现方法有很多,比如说,你可以开一个异步线程,完成一个任务并触发一个委托等,但Flow Graph插件的设计者提供给我们的方法是通过GameplayTag。例如,当任务中玩家死亡,玩家的小弟就会打出一个菜字,那么就有玩家角色所挂载的GameplayTag传递一个Player.Die,同理,Flow Graph也可以通过Tag向携带有Component的Actor通信。也可以通过OnActorRegister,OnActorUnregister来实现与非直接相关的Component的Actor对话。


这样的好处是,在很多情况下,我们游戏任务中的Actor并不会在世界中提前存在,我们无法持有对他的引用,或许你的架构中有一个Subsystem最终会引用到他们,但无论如何,通过Tag都是方便的。
系统仍然允许你通过使用软引用等方法来持有对象的引用,这是有用的,例如,你希望一个Node让玩家角色移动到某个地点,此时使用Notify Actor并不合适,因为Notify Actor的实现要到玩家角色类中实现,这会导致代码耦合度升高,换言之,就是脏。
四. 结语

Flow Graph是一个强大的工具,如果你的项目中含有大量的对话,任务,叙事,机关等,Flow Graph可以允许你在完成对工具的架构之后不书写任何代码完成需求。作为Gameplay程序员,个人认为最终程序员是要把设计的权利交还给设计师的,合理架构数据驱动的工具,实现真正的有牢策划坐,有锅策划背!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|微软交流社区

GMT+8, 2025-1-7 05:02 , Processed in 0.065737 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表