跳到主要内容

5 篇博文 含有标签「Visual Workflow」

Visual event configuration and management

查看所有标签

GCS 如何用可视化内容创作与 FlowGraph,重新定义卡牌肉鸽游戏的创作方式

TinyGiants
Unity Games & Tools Developer

一条从内容创作、玩法编排到运行时验证的端到端创作链路

GCS 从内容编辑、FlowGraph 到战斗运行与 Monitor 验证的完整工作流

上图展示了使用 GCS 创作一款卡牌肉鸽游戏时的完整工作流,先在左侧的 Editor 中完成卡牌、卡组、角色、敌人、状态与遭遇战的内容创作,再用下方的 FlowGraph 对卡牌效果、状态规则与敌人的意图行为进行玩法编排,随后进入 Play Mode 运行战斗,根据右侧的 Monitor 记录战斗状态与流图行为对创作内容进行优化,由此形成一条从内容设计到玩法验证的端到端卡牌肉鸽游戏的完整闭环

整个 GCS 的核心是 FlowGraph,它是这条工作流的核心骨架,而 Editor 则是六类内容创作的基础,负责定义表现层数据、美术资产、数值与资源引用关系,FlowGraph 继续决定卡牌、状态与敌人在战斗中的触发时机、数据来源、规则变化和表现反馈,为了让这些逻辑能够直接阅读、自由组合并由运行时执行,我把卡牌肉鸽常用的触发、数据、运算、流程、动作、决策和表现能力抽象成了 145 个核心节点

一切从可视化内容创作开始​

Game Card Editor 的 Card 模式,包含卡牌列表、字段、Behavior 与卡面预览

Editor 提供了 Card、Deck、Player、Enemy、Status、Encounter 六种内容创作模式,每种模式都包含3个可视化区域,左侧的 List 管理数据库条目,中间的 Inspector 完成内容创作与配置,右侧的 Preview 则同步展示卡面与角色敌人的视觉表现,所有配置被聚合在一个窗口内完成,创作者无需在 Project 窗口里逐个寻找 ScriptableObject,也不必在多个 Inspector 间来回切换

模式负责创作的内容
Card卡牌信息、费用、目标、标签、升级、卡面资源与 Behavior
Deck初始牌组、奖励卡池、卡牌份数与牌组构成
Player角色属性、基础能量、初始牌组、战斗 Prefab 与能量显示
Enemy敌人属性、生命范围、战斗 Prefab、Behavior 与 Intent 摘要
Status状态图标、类型、叠层、衰减规则、层数限制与 Behavior
Encounter参战角色、敌人阵容、奖励牌组、Intent 显示与战斗规则

这六种模式覆盖了一场卡牌战斗所需的主要内容,项目可以替换自己的卡牌 Artwork、状态图标、角色和敌人 Prefab,也可以修改名称、描述、数值等战斗参数

GCS 提供的是内容结构和运行规则,它并不会将项目锁进 Demo 的美术风格、职业设计或数值体系内

可视化内容创作到这里完成的是“游戏里有什么”,而当卡牌需要造成伤害或恢复能量,状态需要在回合开始时结算效果,敌人需要根据生命值来切换行动时,创作就进入了“这些内容该怎样运行”的阶段

Card、Status 与 Enemy 的 Behavior 会从 Editor 直接打开同一套 FlowGraph,玩法创作也从这里真正开始

FlowGraph 是 GCS 构建内容玩法的核心骨架​

我没有把 FlowGraph 设计成若干个固定效果的选择器,也没有用少量的万能节点去覆盖所有的逻辑行为,要知道万能节点看起来省事,但当内容量增加以后,节点内就会塞满互相影响的选项,最终难以被复用,GCS 采用的是一整套被精心设计的原子化节点,每个节点只承担一个清晰的职责,这样可以极大的提高节点灵活性,再复杂的逻辑机制也可以通过动态参数端口与连线逐步形成

把十类节点各取一个放进同一张画布后,FlowGraph 的职责划分会变得非常直观,颜色用于区分节点类别,标题直接说明具体用途,Group 正面还保留了从子图暴露出来的 Volume、Clip、Lifetime 与 Prefab 等常用参数

FlowGraph 十类核心节点与可暴露参数的 Group 节点

当前内置的核心节点总数为 145,其中包括 144 个运行时注册节点和 1 个用于组织子图的 Group 节点

类别数量负责的工作
Entry33从出牌、回合、战斗、状态、单位与事件等时机启动规则
Hook18在伤害、护甲、费用、抽牌、状态等结果提交前读取并改写候选值
Get19读取单位、卡牌、状态、牌堆、能量、变量与事件数据
Operator22完成数学、比较、布尔、随机、集合与数据转换
Flow10组织分支、序列、循环、选择、等待、延迟与 Gate
Action27修改生命、护甲、能量、卡牌、牌堆、状态、回合与单位
Intent6构造敌人行动、权重随机、生命阈值、固定序列与次数限制
Event2发出 GCS 内部事件或可选的 GES 事件
FX7请求 SFX、VFX、动画、飘字、位移与镜头反馈
Group1将多个节点封装成可命名、可进入、可继续嵌套的子图
合计145覆盖从触发到反馈的完整卡牌肉鸽玩法语言

这 145 个节点不是 145 种预制卡牌效果,Entry 和 Hook 决定规则何时发生,Get 与 Operator 准备数据,Flow 安排执行路径,Action、Intent、Event 和 FX 交付结果,Group 再为复杂流图构建嵌套层级,得益于节点的原子化设计,同一个 Change HP 可以用于治疗、生命消耗或生命交换等复核场景的使用,同一个 Change Energy 也可以用于回能、扣能或回合资源的规则编排,而无需再为每种卡牌效果再做一个专用节点

一条玩法规则是怎样通过 FlowGraph 实现的​

最基础的卡牌 Behavior 可以很短,以随包附带的一张卡牌 Posion Arrow 为例,从 On Card Played 开始,先用 Deal Damage 造成伤害,再播放命中反馈,随后通过 Change Status 施加 Poison,并播放对应的中毒效果,控制线从左到右给出结算顺序,伤害数值、目标、Status 与表现资源都会被保存在相应的节点中

Poison Arrow 依次完成伤害、命中反馈、施加 Poison 与状态表现

这个图把逻辑和表现放在了同一个可读路径中,修改伤害不需要进入中毒代码,替换 VFX 或 SFX 也不会影响数值结算,你可以随意添加和调整节点的编排顺序,这会让创作变得特别有趣且灵活

值得注意的是,这张流图中的 Deal Damage 负责的是标准伤害管线,而 Poison 是一个毒状态,它的周期伤害则属于 Status 自己的 Behavior, Card 流图中控制的仅仅是状态的施加动作本身;这样设计的好处是其他卡牌只要施加同一 Status,便可以直接复用这个状态的持续规则

On Card Played 连接 Change HP 的固定自我治疗 FlowGraph

再比如上面这个流图,恢复生命与能量使用的仍然是这组节点,最短的治疗图只需把 On Card Played 接到 Change HP,将目标设为自身并填入正数即可,同一节点换成负数时也能表达生命消耗

抽牌并获得能量的 FlowGraph,由 Draw Cards 与 Change Energy 顺序组成

同样的,资源组合沿用相同方法,Change Energy 调整当前能量,Draw Cards 与 Change Energy 连在同一条控制路径上,就能表达“抽两张牌并获得一点能量”,节点无需知道这张卡最终叫补给、冥想还是战术准备,它只需要清晰的描述实际发生的动作即可

当效果开始读取战斗状态,固定动作便会转化为动态机制,创作者可以灵活读取当前生命、护甲、能量,或者状态层数、牌堆数量、卡牌标签与战斗变量等数据,经过 Operator 计算、比较或筛选,再将结果接入 Action;也可以用 Branch 按条件选择路径、用 Foreach 逐个结算目标集合、用 Choice 将候选项交给玩家选择,或是通过 Delayed Trigger 把后续动作安排到指定回合等

读取 Marked 层数并通过 Condition 与 Branch 选择抽牌或获得护甲

上图先用 Unit Status Stacks 读取自身的 Marked 状态层数,再由 Condition 与常量 0 比较,并把布尔结果交给 Branch,条件成立时执行 Draw Cards,条件不成立时执行 Change Armor,Get、Operator、Flow 与 Action 在同一张图中分别负责读取数据、完成判断、选择路径和提交结果,这就是固定动作转化为状态驱动机制的原理

一条机制因此可以从“造成 6 点伤害”逐步增长为“筛选带有指定状态的敌人,按状态层数计算伤害,再对其余敌人执行另一档结算,命中后再触发状态与表现”,画布中每增加一步,都有一个能够单独查看和调整的节点,也正是基于这种流图驱动的模式,创作者可以拖入任意的新节点、改变连接、替换数据来源或把新的分支插入现有路径,而不用推翻整张卡的具体实现

按照 Marked 状态拆分敌人并执行两档伤害结算

上图从 All Opponents 取得全部敌人,Filter 选出带有 Marked 状态的目标,Exclude 则得到其余敌人,两组目标分别接入 12 点与 8 点伤害,原本单一的群体伤害由此扩展为差异化结算,如果还要按状态层数计算伤害或在命中后追加状态、VFX 与 SFX,只需继续接入对应的数据与动作节点,而已有的目标筛选和结算路径则可以继续保留

Hook 与 Intent 扩展了 FlowGraph 的能力边界​

普通的 Entry 适合表达“某件事情发生以后会做什么”,而对于力量、易伤、费用修改、手牌上限以及状态免疫等行为则是发生在结果提交之前,为了此,GCS 专门设计了 18 个特殊的 Hook 节点来表达这些效果:运行时先给出候选值,通过 Hook 来读取当前值和上下文,经过运算后再使用 Write Hook 来回写(当有特殊规则需要阻止本次处理时,也可以显式取消)

Strength 在伤害提交前读取状态层数并写回候选值

Strength 就是一个典型的 Hook 状态,Damage Dealt Hook 取得本次候选伤害,Status Info 读取 Strength 层数,Math Binary 将两者相加,最后由 Write Hook 回写,所有经过标准伤害管线的卡牌和敌人的意图行动都会得到相同的结果,而无需为每张卡牌主动查询 Strength

聊完了 Hook 我们再来看看 Intent,它解决的是敌人怎样选择、预告并执行行动,6 个 Intent 节点可以组合出各种意图行为,如固定行动、加权随机、生命阈值、行动序列、每场N次和周期行为等

Mire Reaper 使用生命阈值、加权随机与命名 Group 组织敌人意图

上图所示的 Mire Reaper 外层图会先按 40% 的生命阈值切换阶段,再在不同阶段进入各自的加权选择,一般涉及有多段 Boss 战的流图会这么实现,通过将每个候选行动整理成一个 Group 组节点,让外层画布只保留决策结构,使得外层流图的逻辑表达变得更加清晰

Mire Reaper 的 Poison Scythe Group 内层执行子图

双击 Poison Scythe 进入 Group 组节点后,完整的子图行动会继续展开:Leaf Intent 定义玩家看到的攻击意图:造成 14 点伤害、请求命中反馈、施加 2 层 Poison 状态,再播放中毒效果,这种嵌套流图的设计可以极大的提高流图的可读性与可维护性

FX 节点赋予了游戏的战斗表现​

当卡牌造成伤害、恢复生命、施加状态后,玩家可能还希望通过动画、特效、音效或是飘字来丰富它们的战斗表现,为此,FX 家族提供了 Play SFX、Play VFX、Play Animation、Show Floating Text、Flash Unit、Slide Unit 和 Shake Camera等节点,它们与伤害、治疗、状态和 Intent 使用同一套控制路径,确保创作者可以灵活控制音效在何时播放、粒子附着在哪个单位、飘字显示哪个结算结果,以及镜头震动需要持续多久等

由 SFX、VFX、飘字与镜头震动组成的战斗表现流图

用 145 个内置节点组合数以亿计的玩法机制​

节点的价值来自组合,145 个核心节点仅在 4 个有序位置中的理论排列数就已超过 4.4 亿种,实际 FlowGraph 还会继续引入参数、数据来源、目标、分支、循环、Hook、Intent 和 Group 层级,系统会自动排除端口类型或拥有者上下文不匹配的连接,因此,4.4 亿只是用来说明节点组合规模的理论值,并不等同于实际可用的玩法总数,不过这个数字已经足以说明,原子节点进入组合体系后,能够表达的机制远超任何预制效果清单

绝大多数常见的战斗规则都可以直接通过内置的节点组合完成,而无需编写新的节点,创作者可以访问 GCS 的在线文档,我在那里提供了 103 份可直接查看的 FlowGraph 配方,其中包括 52 份卡牌配方、30 份状态配方和 21 份敌人配方,它们覆盖了从选牌、抽弃牌,到费用花费、状态联动、伤害修改、额外回合、复活,以及Boss 阶段、召唤、牌堆干扰与跨图事件等一系列的经典机制,给出了《杀戮尖塔》、《月圆之夜》一类经典卡牌肉鸽玩法的具体流图参考

流图配方

每一份配方中都列出了流图效果、节点连接与参数配置,创作者可以直接理解它们是怎样工作的,再替换目标、数值、状态、资源和分支,逐步构建属于自己的机制体系,不过坦率地讲,绝大多数项目的玩法机制均可通过内置的 145 个节点来实现,确需专属规则时,GCS 仍允许开发者注册自定义的 FlowGraph 节点,并继续使用同一套端口、执行上下文与编辑器工作流来参与创作

对 FlowGraph 创作细节与操作体验的极致打磨​

节点字段适合保存内容创作时已经确定的值,例如 6 点伤害、2 层 Poison 或指定 VFX Prefab,需要让数值在运行时计算时,支持动态输入的字段可以点击右侧端口开关,将固定参数直接暴露为输入端口

Deal Damage 与 Play Effect 中的固定字段和动态输入端口切换

上图所示,字段未连接时继续使用节点中保存的值,当连接上游数据后,本次执行会读取端口结果,例如 Deal Damage.Amount 可以接入力量层数、当前护甲、已消耗能量或牌堆数量等,固定伤害与动态伤害仍然使用同一个节点,区别只在数值从哪里获取,这项设计让参数来源从静态配置扩展到了实时战斗数据,又不会让基础卡牌多出不必要的连线,这便是动态参数端口的设计理念

同一个 Deal Damage 节点在默认状态与自定义名称、端口顺序下的对照

随着流图规模的不断扩大,节点连线开始变得复杂,很容易形成交叉连线,从而影响视觉观感与逻辑梳理,因此,我对节点、字段以及端口的显示名称做了特殊设计,允许创作者通过双击的方式来重命名,创作者完全可以将节点名称改成当前机制更容易理解的表达,端口顺序也支持调整,通过上下拖动改变同侧端口的排列顺序,就能显著减少数据连线交叉的情况

选中 Deal Damage 后展开的节点参考抽屉

创作者不必先记住每个节点的输入、输出和参数细节,可以通过按下 Tab 来展开右侧节点参考栏;当你选中任意节点后,参考栏便会完整显示节点的具体功能、输入与输出端口、参数含义、默认值和相关运行时机等,当你第一次使用 Deal Damage、Hook 或 Intent 等节点时,可以在画布内直接核对,而无需离开当前 Behavior 窗口去查询在线文档

FlowGraph Editor 的 Keyboard Shortcuts and Help 面板

工具栏右侧的 ? 会展示有关流图操作的所有快捷键,以便创作者能够更好、更快的实现流图设计

Group 让复杂流图保持清晰可读​

节点越丰富,越需要一种可靠的层级组织方式,在 GCS 中,选中任意两个以上的节点便可将他们封装成一个 Group 组节点,跨越选区的输入和输出会自动转为 Group 边界端口,原有的执行关系也将会被保留,而无需在创建 Group 节点后重新手动布线

前面的 Mire Reaper ,以及用于组织战斗表现的 Play Effect(Shake) 都是一个 Group,它把 Play SFX、两段 Play VFX、Show Floating Text 与 Shake Camera 收进子图,父图只用于外部表现及其必要的输入展示,父子图之间可以来回穿梭,已有 Group 还能继续和其他节点组成更高一层的 Group,我没有设置可嵌套的层数上限,因此,对于大型的 Behavior ,是可以按照“战斗阶段、机制模块、具体动作”来逐层进行整理的

group

Group 外层仍然可以直接调整,内部没有继续连接的端口会形成边界端口,创作者还可以选择需要暴露在 Group 正面的参数,经常调整的伤害、状态层数、VFX、SFX、Prefab 或持续时间可以留在外层,而对于那些只服务于内部结构的系统参数则可以继续隐藏在子图中,这样既能减少父图的噪声,又不必为了修改一个常用数值而反复进入内部,这对于想要灵活控制流图嵌套的创作者来说会是一个福音

Monitor 让游戏的运行状态可被追溯​

FlowGraph 配置完成后,创作者可以进入 Play Mode,通过 Monitor 来观测这些规则在真实战斗中的运行状态,Monitor 提供了 Battle、Pile、Unit、Phase、Gate、Flow 与 Event 七个页面,分别用于查看战斗快照、牌堆变化、单位状态、阶段推进、等待项、Behavior 执行和事件记录等

Game Card Monitor 的 Battle 页面,集中显示当前战斗状态与数值变化

上图以 Battle 页面为例,当前阶段、回合、Encounter、已打出的卡牌数量、玩家生命与能量、敌人生命、状态以及本次攻击和治疗结果都集中在了同一个页面中,创作者可以直接确认一张卡实际造成了多少伤害、一项状态持续了几个回合、敌人的行动强度是否符合预期,以及整场战斗的资源消耗是否合理

当结果偏离设计预期时,则可以继续切换到 Pile、Unit、Phase、Gate、Flow 或 Event,确认卡牌移动、状态变化、阶段等待、Behavior 入口与事件触发是否正确,再回到 Editor 和 FlowGraph 调整卡牌费用、伤害、治疗、护甲、状态层数、敌人生命和行动强度,然后重新运行战斗并对比结果,这个循环让游戏的数值、战斗节奏与难度曲线的设计建立在游戏实际的运行结果之上,极大的缩短机制玩法的数值平衡与调试周期

这就是 GCS 重新定义的创作方式​

Editor 让卡牌、卡组、角色、敌人、状态与遭遇战拥有统一的可视化内容创作入口;FlowGraph 用 145 个内置节点将玩法机制拆解成可阅读和组合的内置语言;内置运行时执行同一份 Behavior;Monitor 则集中呈现游戏的运行状态、数值变化和执行记录,这四部分共同构成了 GCS 的端到端卡牌肉鸽游戏的创作体验

FlowGraph 是我在 GCS 中投入最多设计与打磨的系统,它把卡牌肉鸽这类游戏最重要的策略机制与规则组合交还给了创作者:节点可以自由连接,参数可以接入动态数据,名称和端口可以按项目语义整理,复杂逻辑可以进入可嵌套的 Group,完成后的机制还可以通过 Monitor 持续观测和调整

当你亲手用它构建几张卡牌、一个持续状态或一名多阶段的敌人后,对这套创作方式的理解也会更加深入,你可以从最简单的伤害和治疗开始,逐步加入状态联动、Hook、敌人决策、表现反馈和属于项目自己的玩法体系,并将这些内容持续维护到一款能够商业化发行的卡牌肉鸽游戏中,让整个创作、验证与调整的过程始终在同一套工作流中完成

更进一步,GCS + AI-Agent的开发模式或将会成为一种全新的创作体验,GCS 中的内容与流图本身就是结构化、可执行并能够被验证的创作资产,因此你可以让 AI-Agent 在明确的边界内参与其中,以加速内容创作生成、规则编排与玩法迭代的速度,如果你对这种创作模式感兴趣,或是想要了解更多有关GCS的设计细节,欢迎加入 TinyGiants 官方 Discord 社区参与讨论~!


TG官方矩阵

Official Website: https://tinygiants.tech

Documentation: https://tinygiants.tech/docs/gcs

Asset Store: https://tinygiants.tech/gcs

Discord: https://tinygiants.tech/discord/gcs

Youtube: https://tinygiants.tech/youtube/gcs

Unity Forum: https://tinygiants.tech/forum/gcs

可视化与 API 事件分层:可扩展项目的最佳实践指南

TinyGiants
Unity Games & Tools Developer

随着项目规模增长,我最常听到的问题之一是:"我应该用可视化工具还是脚本 API?" 答案是两者都用——但知道什么场景下各自最有效,才是区分整洁可扩展事件架构与最终不堪重负架构的关键。

在观察了各种规模团队使用 GES 的方式后,我想分享一套分层方法,无论你有 50 个事件还是 500 个,都能保持项目的可维护性。

看不见的事件链:你无法调试看不见的东西

TinyGiants
Unity Games & Tools Developer

玩家死了。死亡音效响了。布娃娃激活了。UI 弹出"你死了"。游戏自动存档。数据分析事件发出去了。重生倒计时开始了。六个不同的系统,全部在响应一个事件:OnPlayerDeath。但我的问题是——这些关系记录在哪?

不在你的代码里。不在项目管理工具里。不在任何图表里。它存在于一个地方:最初配置它的那个人的脑子里。如果那个人半年前离职了,那它哪儿都不存在。

这就是事件驱动架构的脏秘密。我们采用它是因为它解耦了系统。我们庆祝 AudioManager 不需要引用 UIManager 了。但我们从不谈代价:执行流变得不可见了。而不可见的东西,从定义上来说,就是没法可视化调试的。

告别 if-else 地狱:可视化条件逻辑的正确打开方式

TinyGiants
Unity Games & Tools Developer

每个游戏说到底就是一大堆条件判断。"只在敌人没有免疫火焰伤害、且玩家有火焰 buff、且暴击判定通过的时候才造成火焰伤害。"在原型阶段,你随手在回调里写个 if 就继续了。三十秒搞定,能跑,感觉效率很高。

然后原型进入正式开发。那些三十秒写的 if 语句开始疯狂繁殖。一个变五个,五个变五十个,五十个变成"第二关 Boss 的掉落概率到底在哪个鬼条件里控制的?"然后你的策划站在你身后问能不能把一个伤害阈值从0.3改成0.25,你在解释这得重新编译。

欢迎来到 if-else 地狱。常住人口:每一个活过三个月的 Unity 项目。

策划不写代码也能配事件:设计师与程序员的协作问题

TinyGiants
Unity Games & Tools Developer

周二下午三点,你的策划凑过来说:"诶,玩家受到50点以上伤害的时候,屏幕震动能不能再猛一点?打击音效延迟半秒再播?还有中毒的跳伤改成1.5秒一次吧,2秒太慢了。"

三个改动。从策划的角度来看,可能也就十五秒的思考量。但实际上会发生什么呢:你关掉 Scene 视图,打开 IDE,等它加载,搜索伤害处理的代码,找到屏幕震动强度那个值——埋在某个方法里面。改掉。然后找音效延迟——在另一个类里。改掉。再找中毒协程——又在另一个类里,而且 tick 频率藏在 WaitForSeconds 的参数里。改掉。保存三个文件。切回 Unity。等重新编译。测试。

八分钟后,策划说:"算了,震动还是原来的好,中毒能不能试试1.8秒?"