卡牌创作
定义一张卡的费用、手牌中的呈现,以及结算时运行哪张 FlowGraph。
适合在 Workbench Card 模式中创建或审阅卡牌内容的开发者。卡牌是玩家的主要行动来源。一个卡牌定义控制它在手牌中的显示、打出费用,以及结算时运行的行为图。这些内容都在同一个窗口中编辑:打开 Tools > TinyGiants > GCS > Game Card Editor,切换到 Card 页签。

Demo 自带的 80 张卡全部使用这套流程制作。字段含义不明确时,可以打开一张 Demo 卡(例如 Poison Arrow 或 Shield Bash)与自定义卡牌对照。
创作顺序
从零创建一张卡时,建议按以下顺序处理:
- 先用一句话写清这张卡对玩家承诺的效果。
- 填写 Name、Description、Cost、Type 和 Rarity。
- 如果表现资源已经存在,设置 Icon 和 Template。
- 添加 Tags 用于过滤和联动;只有需要内置规则行为时才添加 Keywords。
- 打开 Edit FlowGraph,连好行为。
- 把卡放进一个卡组,进战斗测试。
卡牌文本尚未明确前,不建议搭建行为图。行为图应实现卡面文字承诺的效果;第 1 步写下的句子,是之后校对文字与行为是否一致的基准。
基础字段
| 字段 | 作用 |
|---|---|
| Name | 手牌和列表行中的显示名称。非空时 Workbench 会同步重命名卡牌资产。 |
| Description | 显示在卡面上的规则文本。保持与行为图一致。 |
| Cost | 打出这张卡所需的能量。只接受整数,编辑器会把它限制在 0 或更高。这是印在卡上的基础费用;一旦 Card Cost Hook 或 Modify Card Cost 效果介入,玩家实际支付的费用可以不同。 |
| Type | 用于卡框颜色、过滤和分组的卡牌分类。下拉提供 Basic、Skill、Curse、Support、Burst,外加数据库中已经用过的所有类型;输入新标签即创建。 |
| Rarity | 奖励与分组标签。下拉提供 Common、Rare、Epic、Legendary,外加已用过的自定义值。留空会回退到 Common。 |
| Tags | 项目自用的自由标签,用于过滤和联动。本身没有内置行为。 |
| Keywords | 带内置规则行为的引擎关键词,从下拉列表中选取。见下表。 |
| Upgrade | 升级后变成的卡。None 表示没有升级路径。 |

Tags 和 Keywords 在 Inspector 中形式相似,但行为不同。Tags 是项目自定义标签,在 FlowGraph 或代码读取它之前,引擎不会处理它。Keywords 来自卡牌关键词注册表,带有内置规则行为。需要内置行为时,应从 Keywords 下拉中选择,而不是填入 tag。
Demo 的 Poison Arrow 展示了完整字段配置:Cost 1、Type Skill、Rarity Common、一个 Attack 标签,描述与行为图保持一致。

内置关键词
Keywords 下拉的选项来自关键词注册表(C# 中的 [CardTag] 类型)。项目程序集可以注册新关键词。GCS 内置五个关键词,每个都有明确规则:
| 关键词 | 规则行为 |
|---|---|
Exhaust | 打出后进入消耗堆而不是弃牌堆,弃牌堆重洗时不会回来。 |
Ethereal | 回合结束时若仍在手牌中,会被消耗而不是弃掉。 |
Retain | 回合结束时保留在手牌中,不被弃掉。只在遭遇战规则设定回合末弃手牌时才有意义;保留手牌的规则下,所有卡本来就留着。 |
Innate | 战斗开始时被移到抽牌堆顶部,因此会出现在起手手牌里。Innate 卡多于起手位时,随机选出一部分。 |
Unplayable | 永远不能打出。它作为死牌留在手牌中,常用于诅咒和联动效果。 |
升级
一张卡和它的升级形态是两个独立的卡牌定义。先创建强化版卡牌,再把基础卡的 Upgrade 指向它。运行时某个机制升级某份卡后,该卡实例会改用升级定义的费用、文本和行为图。Demo 的 Strike 以这种方式升级为 Heavy Strike;升级卡本身不需要出现在任何卡组中。
视觉字段
Visual 区域有两个槽位。Icon 是卡面和列表行使用的美术 sprite。Template 是渲染为卡面的 prefab,留空时表现层会回退到占位显示。
机制测试阶段可以使用临时美术。占位卡面足够验证伤害数字和目标选择,正式美术可以后续替换。
目标模式
目标选择是卡牌定义上的数据:TargetMode 字段决定打出这张卡时是否要求玩家指向一个单位,行为图在运行时读取这个选择。
| 模式 | 玩家的体验 |
|---|---|
None | 不选单位直接结算。抽牌、获得能量属于这一类。 |
Self | 卡牌作用于玩家单位,无需选择。 |
SingleEnemyUnit | 玩家把卡拖到一个存活敌人身上。 |
AllEnemyUnits | 卡牌命中所有存活敌人,无需选择。 |
只有 SingleEnemyUnit 需要选定目标,其余三种模式由引擎自动解析。在图里,选中的单位对应 Opponent 目标选项,这就是 Poison Arrow 的 Deal Damage 节点瞄准 Opponent 的原因。从代码打出卡牌时也是同一份契约:
// TryPlayCard(CardInstance card, UnitState target): card is a hand instance.
// Single-enemy cards need a target unit; every other mode takes null.
var arrow = GCSApi.Hand()[0];
GCSApi.TryPlayCard(arrow, GCSApi.FirstAliveEnemy());
GCSApi.TryPlayCard(GCSApi.Hand()[1], null);
通过代码打出单体卡但未传入目标时,引擎会回退到第一个存活敌人,而不是让这次出牌失败。
保持目标模式和行为图一致。描述写着"所有敌人"时,图应解析所有敌人,而不是只读取选中目标;需要玩家点击敌人的卡牌,目标模式不应为 None。
行为图
在 Behavior 区域点击 Edit FlowGraph。图会在独立窗口中打开,窗口顶栏显示宿主名称;卡名为 Poison Arrow 时,标题为 Poison Arrow / FlowGraph。图中存在入口后,折叠面板会把入口列为可点击 chip,用于跳回对应位置。


一张有效的卡牌图需要回答三个问题:
| 问题 | 示例回答 |
|---|---|
| 它什么时候运行? | 打出这张卡时。 |
| 它影响谁? | 选中的敌人、所有敌人、玩家自己,或解析出的一组单位。 |
| 它改变什么? | 伤害、护甲、抽牌、状态层数、能量、VFX 或存储值。 |
Demo 的 Poison Arrow 是这样回答的:一个 On Card Played 入口,一个指向选中敌人的 Deal Damage 节点(Amount 3),然后一个 Change Status 节点给目标叠 2 层 Poison,中间穿插播放箭矢命中和毒雾的效果节点。

第一版建议保持线性结构:入口、目标、一两个状态变更,表现节点放在最后。分支、循环和随机挑选应在简单版本验证通过后再加入。Rapid Fire 是 Demo 中的进阶示例:花 2 点能量,一个 Loop 节点执行 4 轮,每轮对随机一个敌人造成 3 点伤害。

卡牌怎样进入战斗
一张卡可以完全合法,却始终不在战斗里出现。运行时它必须走通这条链:
卡牌必须位于启用的卡牌数据库中,某个卡组必须以至少 1 份引用它,遭遇战的玩家单位必须使用该卡组(或运行期 master deck 包含这张卡),战斗还必须启动对应遭遇战。新卡不出现时,先沿这条链排查,再检查行为图。
校验
Card 模式报告两类问题:
- Name 为空是错误。
- FlowGraph 校验器在行为图中发现的问题是警告。
Deck 模式还有自己的检查:条目没有指定卡牌、条目 Copies 低于 1,都是错误。校验无法判断可达性:一张结构正确的卡,仍可能因为没有被启用卡组引用而无法进入战斗。
常见错误
| 症状 | 可能原因 |
|---|---|
| 卡出现了但打不出去 | 费用超过当前能量、战斗不在玩家阶段、卡上有 Unplayable,或某个 Card Playable Hook 拦下了它。 |
| 卡要求了错误的目标 | TargetMode 与图中的目标解析不一致。 |
| 卡牌文本与行为不一致 | 修改行为图后没有同步更新描述。应立即修正文案或行为图。 |
| 升级没有效果 | Upgrade 指向 None,或整局中没有任何机制升级这张卡。 |
| 关键词无效 | 它被填成了 tag,而不是从 Keywords 下拉中选取。 |