玩家创作
定义玩家控制谁、携带哪套卡组,以及生命和能量如何显示
Iron Resolve 已经配置完成并绑定到 Squire,Player 模式会把角色名称、战斗预制体、生命、基础能量、资源 UI 和这套初始卡组集中保存在同一份 GamePlayerUnit 中
先确认当前场景的 GameCardManager 已启用至少一个 Player Unit Database,数据库配置决定 Game Card Editor 能够列出、创建和编辑哪些玩家角色
打开 Game Card Editor
Tools > TinyGiants > GCS > Game Card Editor
在窗口顶部选择 Player,再从左侧定位 Squire
上图展示了 Player 模式围绕 Squire 展开的完整工作区,左侧 List 选择当前角色,中间 Inspector 保存名称、战斗预制体、70 点生命、3 点基础能量和 Iron Resolve,右侧 Preview 检查界面与预制体,Used By 则显示 The Threshing Field 对 Squire 的直接引用
List 中当前选中的 GamePlayerUnit 是整个工作区的数据源,Inspector、Preview 与 Used By 都会随选择同步更新
从 List 选择玩家角色
Player 模式只列出当前 GameCardManager 已启用的 Player Unit Database 中的非空角色,先在 Database 中选择要写入的数据库
+ 会创建以 NewPlayerUnit 为基名的子资产,新角色默认使用 70 点生命、3 点基础能量和 Energy 资源名,Name、Icon、Template 与 Starting Deck 仍需填写
− 会在确认后删除当前角色,复制按钮会保留全部字段并创建副本,副本暂时沿用原 Name,修改为新的非空名称后才会重新同步子资产名
搜索与名称排序读取子资产名,Tags 多选筛选会保留命中任一标签的角色,排序按钮会在数据库顺序、名称升序与名称降序之间切换,拖动列表行只改变数据库中的创作顺序
批量整理时,可以使用 Ctrl/Cmd 或 Shift 多选,再执行 Duplicate、Tag +、Tag − 或 Delete,Ctrl/Cmd+C 与 Ctrl/Cmd+V 还可以把玩家角色复制到另一个已启用的同类型数据库,完整列表交互见 Game Card Editor
每个列表行都会显示角色 Icon、名称、Base HP 和 Base Energy,无需打开 Inspector 即可比较各角色的基础生命与基础能量

PresetPlayerUnitDatabase 当前包含 12 个随包玩家角色,选中的 Squire 在列表中显示 70 HP · 3 Energy
保持 Squire 处于选中状态,先配置用于列表与项目 UI 的名称、说明和头像,再绑定战斗中生成的预制体
建立角色身份与战斗表现
Basic
Basic 保存 Name、Description 与 Tags,分别控制显示名称、身份说明和标签匹配
| 字段 | 配置与使用位置 |
|---|---|
| Name | 角色显示名称,Name 改为非空值时会同步修改子资产名,Name 为空时界面会回退显示子资产名,但 Validation 仍会报告错误 |
| Description | Display 预览和项目角色信息界面可以读取的身份说明,随包 Demo 会把这段文字显示在角色悬停信息中 |
| Tags | 供 List 筛选与项目逻辑使用的自由标签,FlowGraph 的 Filter 节点会区分大小写,只要单位 Tags 命中任一指定标签即可通过筛选 |
将 Name 设为 Squire,保留角色说明 A burlap recruit still learning to take a hit.,再添加 Warrior 与 Novice

Display 会读取 Squire 的 Name 与 Description,List 搜索读取子资产名,单位筛选读取 Tags,标签如何参与 FlowGraph 目标集合见目标选择
Visual
Icon 是 List、Display 预览和项目角色 UI 使用的头像,随包 Demo 也会把它用于角色悬停信息
Template 写入 GameUnit.Prefab,Preview 的 Render 会在隔离视图中实例化这个 Prefab
GCS 核心战斗状态机不会替项目生成场景对象,随包 Demo 由 BattleBoard 实例化 Template 并绑定 UnitView
为 Squire 选择战士 Avatar 与 Prefab
Squire 的 UI 头像与战斗预制体已经分别绑定,接着用 Attributes 设置它进入战斗时的生命与基础能量
确定战斗初始状态与卡组
Attributes
| 字段 | 运行时含义 |
|---|---|
| Base HP | 同时作为玩家进入战斗时的当前 HP 与最大 HP,普通治疗不会超过最大 HP,编辑器输入最低钳制为 1 |
| Base Energy | 玩家每回合开始时的基础能量,编辑器输入最低钳制为 0 |
将 Squire 的 Base HP 设为 70,Base Energy 设为 3
战斗启动时,新建的 PlayerUnitState 会拥有 70/70 HP 和 3 点当前能量,随后每个玩家回合开始都会重新计算本回合能量
当 BattleRules.StartingEnergy 大于 0 时,它会替代 Base Energy,再叠加 Run Energy Bonus,并交给 OnEnergyPerTurn Hook 调整,Hook 未取消时结果最低钳制为 0,取消时保留调整前的值,完整回合位置见战斗循环
GainEnergy() 可以让当前能量暂时超过每回合上限,SetEnergy() 则会把结果限制在当前 MaxEnergy 内,Energy Display 中的名称、说明和图标不会参与这些计算
生命与能量确定后,再为 Squire 绑定 Starting Deck,为没有 Master Deck 的战斗提供初始牌组
Starting Deck
点击卡组卡片右侧第一枚按钮可以选择或更换 Starting Deck,第二枚按钮会在 Game Card Editor 中打开对应卡组,× 会清空引用,双击卡片也会打开选择器
选择器优先读取当前场景启用的 Deck Database,只有一个非空数据库时显示平铺列表,存在多个数据库时按数据库分组,没有可用分组时才会回退搜索项目中的 GameDeck
为 Squire 选择已经配置完成的 Iron Resolve

卡组卡片显示 Iron Resolve 的总卡数为 17,按有效卡牌引用与份数计算的平均基础费用为 0.71,引用缺失或份数错误需要在卡组创作中修正
持久 Master Deck 为空时,GCS 才会按 Iron Resolve 各条目的 Copies 临时建立战斗卡组,这份回退结果不会写回持久 Master Deck,已有 Master Deck 则会完全替代 Starting Deck
GamePlayerUnit 本身没有独立 Behavior,玩家能够执行的动作来自卡牌 Behavior,持续规则则由状态、Encounter 与运行时 Hook 共同提供,执行关系见 FlowGraph 模型
从初始抽牌堆到手牌、弃牌堆与消耗堆的转换见卡牌、手牌与牌堆
卡组确定后,再用 Energy 配置卡牌费用资源在界面中的名称、说明和图标
定义能量资源的界面表达
| 字段 | 显示职责 |
|---|---|
| Name | Energy、Mana、Focus 等资源名称 |
| Description | 项目可以用于 Tooltip 或规则说明的资源文本 |
| Icon | 项目能量计数旁边可以显示的资源图标 |
将 Squire 的能量名称设为 Energy,说明设为 Per-turn resource for playing cards.,再绑定战士能量图标

这三个字段只是表现元数据,不会改变 Base Energy、Starting Energy、Run Energy Bonus 或 Hook 计算出的数值
Game Card Editor 的 Energy Display 会同时预览资源名称、说明和图标
进入 Play Mode 后,随包 Demo 中的 UnitEnergyDisplay 目前只读取 Name 与 Icon,项目 UI 可以按需继续读取 Description
这些静态配置完成后,右侧 Preview 会分别检查角色卡片、Template 和能量资源的显示结果
在 Preview 中检查最终表现
Display
Display 会把 Icon、Name 与 Description 显示为一张紧凑的角色卡片,先确认头像与文字属于同一个角色

Display 已经确认头像、名称与说明能够组合显示,Render 接着检查 Visual 中绑定的 Template 能否被编辑器实例化并正常绘制
Render
Render 在隔离预览场景中实例化 Template,按住鼠标左键旋转,右键或中键平移,滚轮缩放,右上角按钮恢复自动取景

当前预览只确认 Prefab 能够被编辑器实例化并渲染,实际战斗位置、根节点缩放、场景锚点和组件依赖仍需进入 Play Mode 检查,随包 Demo 还会通过 BattleBoard 的 Unit Scale 与 Unit Offset 调整最终布局
Template 能够正常渲染后,再用 Energy Display 检查能量图标、名称和说明是否匹配
Energy Display
Energy Display 显示 Icon、Name 与 Description,Icon 为空时会改用带有 Base Energy 数值的圆形占位,它不会读取当前战斗中的实时能量

三项 Preview 结果确认后,查看 Issue Badge,检查当前 Player Unit Database 是否仍有 Name、StartingDeck 或 Template 缺失
清除 Validation 问题
Player 模式的 Issue Badge 扫描当前所选 Player Unit Database 中的全部角色,不只统计正在查看的 Squire
| 级别 | 触发条件 |
|---|---|
| Error | Name 为空 |
| Warning | StartingDeck 为空 |
| Warning | Template 引用为空 |
这些 Issue 不会阻止保存、删除或进入 Play Mode,点击 Issue 条目中的 Ping 只会定位到存在问题的角色或字段
Validation 不检查 Icon、Description、Tags、Base HP、Base Energy、Energy Display,也不会继续验证 Starting Deck 的卡牌条目或 Template 的运行时组件
通过编辑器字段修改 Base HP 与 Base Energy 时会应用最低值限制,但外部序列化或旧资产留下的非法值不会由 Player Validation 自动修复
这些结构问题处理完成后,再用 Used By 确认当前角色被哪些 GameEncounter 的 Player Unit 字段直接引用
用 Used By 确认遭遇战入口
Used By 只扫描当前场景 GameCardManager 已启用 Encounter Database 中的直接引用,并列出 GameEncounter.PlayerUnit 指向当前角色的条目
点击结果会切换到 Encounter 模式并定位对应资产,未启用数据库、其他场景、Prefab、代码引用和运行时形成的间接引用不在扫描范围内,删除角色时也不会提供引用保护

图中的 The Threshing Field 已经把 Squire 保存为 Player Unit,这项结果只证明直接引用成立,要形成完整的可玩遭遇战,还需继续检查敌人、奖励卡组、战斗规则和场景接入,完整字段见遭遇战创作
打开随包场景 1-The Threshing Field 并进入 Play Mode,确认 Squire 的 Template、70 点生命、3 点能量与 Iron Resolve 是否共同生效
画面中的 Squire 已经以 70/70 HP 和 3/3 能量进入战斗,5 张手牌与 12 张抽牌堆合计 17 张,与 Iron Resolve 的总卡数一致,这次运行同时确认战士 Template 能够生成、角色属性已经生效,并且 The Threshing Field 使用的玩家角色正是 Squire
其余 11 场可运行 Demo 及场景入口见 Demo 场景索引
通过 GCSApi 读取角色内容与战斗状态
GamePlayerUnit 保存可复用的角色定义,GameEncounter.PlayerUnit 决定一场战斗使用哪份定义,GCSApi.StartBattle() 接收的是完整 Encounter,而不是单独的玩家角色
战斗启动后,BattleStateMachine 会从这份定义创建 PlayerUnitState,当前 HP、护甲、能量、状态和死亡标记都保存在这个 UnitState 中,不会回写 GamePlayerUnit
GCSApi 同时提供玩家内容查询,以及当前战斗状态的读取、修改和事件订阅入口
- 查找玩家内容:
ActivePlayerUnitDatabases()、PlayerUnits()、FindPlayerUnit(guid) - 读取当前玩家:
Player()、PlayerEnergy、MaxEnergy、Hp()、MaxHp()、Armor()、HpPercent()、IsAlive()、IsDead() - 修改战斗状态:
DealDamage()、LoseHp()、Heal()、SetHp()、GainArmor()、LoseArmor()、SetArmor()、KillUnit()、ReviveUnit()、GainEnergy()、LoseEnergy()、SetEnergy() - 监听状态变化:
OnUnitHpChanged()、OnUnitDied()、OnEnergyChanged()、OnEnergyGained()、OnEnergySpent()
Player() 返回当前战斗中的 UnitState,没有活动战斗时返回 null,它不会返回 GamePlayerUnit
当 GCSApi.Manager 非空时,PlayerUnits() 每次调用都会新建列表并汇总已启用数据库中的玩家角色,频繁读取时应当缓存结果
各入口的参数、返回值与调用时机见 GCSApi 使用指南
Squire 现在已经带着 Iron Resolve、70 点生命与每回合 3 点基础能量进入 The Threshing Field,在 Game Card Editor 顶部切换到 Enemy,按敌人创作继续检查同一场战斗中的 Strawman