跳到主要内容

敌人创作

Guide

定义敌人的身份、HP 范围、预制体,以及选择并结算意图的行为图

Squire 已经带着 Iron Resolve 进入 The Threshing Field,同一场战斗中的 Strawman 则由一份 GameEnemyUnit 定义,它把敌人名称、Tier、Tags、HP 范围、战斗预制体和 Behavior 保存在一起

先确认当前场景的 GameCardManager 已启用至少一个 Enemy Unit Database,数据库配置决定 Game Card Editor 能够列出、创建和编辑哪些敌人

打开 Game Card Editor

Tools > TinyGiants > GCS > Game Card Editor

在窗口顶部选择 Enemy,再从左侧定位 Strawman

Game Card Editor 的 Enemy 模式围绕 Strawman 展开 List、Inspector、Preview 与 Used By

上图呈现了 Enemy 模式围绕 Strawman 建立的完整创作视图,左侧 List 决定当前编辑对象,中间 Inspector 保存身份、战斗预制体、14–18 HP 与 Behavior,右侧 Preview 同步核对配置结果,Used By 则把这份敌人定义连接到引用它的遭遇战

四个区域共享当前选中的 GameEnemyUnit,因此先在 List 确认 Strawman,后面的配置、预览与引用追踪就会沿同一份数据连续展开

在 List 中确认 Strawman

Enemy 模式只会从当前 GameCardManager 已启用的 Enemy Unit Database 中读取非空敌人,切换 Database 时,当前选择与右侧工作区也会切换到对应数据库

每个列表行都会显示敌人 Icon、名称、Tier 与 HP 范围,无需打开 Inspector 即可比较同一数据库中各敌人的 Tier 与 HP 范围

PresetEnemyUnitDatabase 中的敌人列表,Strawman 显示 Normal 与 HP 14–18

PresetEnemyUnitDatabase 当前包含 16 个随包敌人,Normal、Elite、Boss 与 Summon 各 4 个,选中的 Strawman 在列表中显示 Normal · HP 14–18

List 还承担当前 Enemy Unit Database 内的资产管理,具体操作与结果如下

操作结果
创建+ 创建以 NewEnemyUnit 为基名的子资产,默认使用 Normal Tier 和 20–30 HP,NameDescriptionIconTemplate 与 Tags 为空,Behavior 已创建但没有节点或连接
复制复制当前字段与 Behavior 并生成独立副本,子资产名追加 _Copy,显示用的 Name 暂时保持不变
删除 在确认后删除当前敌人,不会保护或迁移已有引用
搜索与筛选搜索和名称排序读取子资产名,Tier 使用忽略大小写的精确匹配,Tags 保留命中任一所选标签的敌人,标签比较区分大小写
排序与拖动排序按钮在数据库顺序、名称升序与名称降序之间切换,拖动列表行只改变数据库中的创作顺序
批量操作多选复制、批量添加或移除 Tag、批量删除,以及通过 Ctrl/Cmd+CCtrl/Cmd+V 在同类型的活动数据库之间复制

窗口级的选择、快捷键与批量交互见 Game Card Editor

确认列表中的 Strawman 显示 Normal · HP 14–18 后,保持它处于选中状态,先配置用于列表、界面与运行时分类的身份信息,再绑定战斗表现使用的 Icon 与 Template

定义敌人身份与战斗表现

Basic

字段配置与使用位置
Name敌人显示名称,改为非空值时会同步修改子资产名,为空时 List 与 Display 会回退显示子资产名,但 Validation 仍会报告错误
DescriptionDisplay 预览与项目敌人信息界面可以读取的说明,随包 Demo 会把这段文字显示在单位悬停信息中
Tier可选择 NormalEliteBoss 或当前项目中的其他标签,写入运行时 EnemyUnitState.Tier 并参与 Tier 筛选、单位属性读取和相关事件
Tags供 List 筛选与项目逻辑使用的自由标签,FlowGraph 的 Filter 节点会区分大小写,只要单位 Tags 命中任一指定标签即可通过筛选

Name 设为 Strawman,保留说明 Burlap-stitched fieldhand.,选择 Normal Tier 并添加 Warrior Tag

Strawman 的 Basic 配置,包含名称、说明、Normal Tier 与 Warrior Tag

Tier 本身不会自动放大 HP 或伤害,但随包 Demo 会用它调整单位缩放、位置偏移和意图高度,Tier 与 Tags 如何参与单位集合筛选见目标选择

Visual

Icon 用于 Enemy List、Display 预览和随包 Demo 的单位悬停信息,Template 则写入 GameUnit.Prefab,供编辑器 Render 与项目表现层实例化

Strawman 选择敌人 AvatarPrefab

Strawman 的 Visual 配置,Icon 引用 Avatar,Template 引用 Prefab

GCS 核心战斗状态机只创建 EnemyUnitState,不会自动生成场景对象,随包 Demo 由 BattleBoard 读取 state.Source.Prefab、实例化 Template 并绑定 UnitView

身份与表现引用确定后,Attributes 会决定每次为 Strawman 创建 EnemyUnitState 时使用的生命范围

确定进入战斗时的 HP

StrawmanHP Min 设为 14HP Max 设为 18

Strawman 的 Attributes 配置,HP Min 为 14,HP Max 为 18

运行时会在 1415161718 五个整数中等概率选择一次,并把结果同时写入新建 EnemyUnitState 的当前 HP 与最大 HP,因此该范围的平均初始生命为 16

需要固定生命时把两项设为相同值,同一 Encounter 重复引用 Strawman 时,每个槽位仍会创建独立状态并分别随机 HP

编辑 HP Max 时,Game Card Editor 会把它限制为不低于当前 HP Min,但提高 HP Min 不会同步改写已有 HP Max,脚本或旧资产留下的反向范围也不会自动修复,Validation 会报告 HpMin > HpMax

HP 决定敌人能够承受多少伤害,Behavior 则决定它在每个敌人阶段公布哪项意图并执行什么行动

用 Behavior 规划意图并结算行动

点击 Edit FlowGraph 打开当前敌人的 Behavior,按钮下方会显示顶层 Pattern、Leaf Intent 与 Action 数量

Strawman 的 Behavior 区,包含 Edit FlowGraph 与 Patterns 1、LeafIntents 3、Actions 4

这组摘要只统计顶层节点,Leaf Intent 会单独计数,Pattern 不含 Leaf,Action 只统计 MutatorNode,Group 内部节点不会进入摘要

Strawman 的顶层图共有 14 个节点,4 个 Group 内还包含 21 个节点,因此完整序列化规模为 35 个节点

在 FlowGraph Editor 中打开这条完整行为图

Strawman 的 FlowGraph 从 On Enemy Behavior Start 进入 Weighted Random Pattern 并分出 Attack、Defend 与 Multi

上图从 On Enemy Behavior Start 进入 Weighted Random Pattern,再把三个权重分支分别连接到一个 Leaf Intent 及其行动链,图中的可见关系对应以下运行结果

分支权重公布的意图敌人阶段执行的行动
Attack50Attack对玩家造成 8 点原始伤害
Defend25Defend自身获得 8 Armor,再对玩家造成 4 点原始伤害
Multi25Multi循环 3 次,每次对玩家造成 3 点原始伤害,共结算三次独立伤害

运行时只会使用 Behavior 中第一个顶层 OnEnemyBehaviorStart,并从它的 Out 开始规划

在抵达 Leaf Intent 之前,这条路径只能连续经过 Pattern,Action、状态与表现链必须位于 Leaf 之后

如果规划在抵达 Leaf 之前遇到 Action、Control、Group 或其他节点,运行时会立即停止并得到零个 Intent,当前 Validation 不会报告这项结构问题

战斗开始时,GCS 会沿这条有效的 Pattern 路径选择一个 Leaf,将 Leaf ID、Pattern 路径和意图保存在该敌人的 EnemyUnitState 中,敌人阶段会执行已经公布的同一个 Leaf,而不是再次随机

行动完成后,Sequence、Once Per Battle 与 Every N Turns 等有状态 Pattern 才会推进内部进度,敌人阶段结束后再为下一回合规划新意图,完整阶段位置见战斗循环

当前运行时每次规划会得到零个或一个 IntentEntry,其中是否包含可显示的数值,取决于 Leaf 后的线性 Out 路径

Attack、Defend 与 Heal 会沿这条路径查找第一个对应的伤害值、护甲值或正数治疗值,并将其写入意图数值,Multi、Buff、Debuff 与 Special 的意图数值保持 -1

Encounter 的 Enemy Intent Display 决定这项计划如何对外显示

模式对外结果
FullOnEnemyUnitIntentChanged 携带意图类别和经过相关 Hook 预估的显示数值
IconOnly事件保留意图类别,但把显示数值改为 -1
Hidden内部仍然规划并保存意图,但不发送 OnEnemyUnitIntentChanged

CurrentIntentTag()CurrentIntentValue()PendingIntents() 读取的仍是内部原始计划,不会按上述显示模式改写,Encounter 中的完整选项见遭遇战创作

内置敌人 Pattern 还包括 Sequence PatternHP Threshold PatternOnce Per BattleEvery N Turns,节点端口和运行规则见 Intent 节点

Strawman 用一个权重分支建立了最小完整敌人回路,更复杂的 Behavior 可以在同一个入口后继续叠加生命阈值、多个权重分支、状态和表现节点

Mire Reaper 的 FlowGraph 用 HP Threshold 与 Weighted Random Pattern 组织多组意图、状态和表现

上图中的对象已经从 Strawman 切换为 Mire Reaper,它先按 HP Threshold 选择高 HP 或低 HP 分支,再让两个 Weighted Random Pattern 分别组织 Poison、Weak、伤害与表现链路,完整可复用结构见敌人行为配方

确认这种复杂 Behavior 的扩展方式后,回到 Game Card Editor 并在 Enemy List 重新选中 Strawman,右侧 Preview 会依次呈现身份卡片、Template、入口摘要与意图构成

在 Preview 中检查编辑结果

Display

Display 会把 Icon、Name、Tier 与 Description 显示为一张敌人身份卡片,先确认 Strawman 的头像、名称、Normal 标签和说明均已显示且内容正确

Strawman 的 Display 预览,包含头像、名称、Normal Tier 与说明

Display 只证明编辑器能够读取这些字段,项目运行时 UI 是否沿用同一布局仍由自己的表现层决定,Template 则需要在 Render 中单独检查

Render

Render 会在隔离预览场景中实例化 Template,按住鼠标左键旋转,右键或中键平移,滚轮缩放,右上角按钮恢复自动取景

Strawman 的 Render 预览,敌人 Template 在隔离视图中完成渲染

当前预览只确认 Prefab 能够被编辑器实例化并渲染,BattleBoard 锚点、Tier 缩放与偏移、场景排序、运行时绑定和交互组件仍需进入 Play Mode 检查

Behavior Summary

Behavior Summary 会列出 Behavior 中的顶层 Entry,并从每个 Entry 沿名为 Out 的第一条控制连接向后显示最多 8 层

Strawman 的 Behavior Summary 显示 OnEnemyBehaviorStart 进入 WeightedRandomPattern

OnEnemyBehaviorStart → WeightedRandomPattern 只确认入口与第一段控制链存在,摘要遇到 Pattern 分支时不会展开所有 Leaf,也不会证明某条分支可以执行到 Action

Intents

Intents 会遍历 Behavior 的顶层节点,并按 Leaf Intent 的类别和数量生成分布条

Strawman 的 Intents 预览显示 Attack 1、Defend 1 与 Multi 1

Strawman 有 Attack、Defend 与 Multi 各一个,因此预览显示三个等宽区块,这里统计的是 Leaf 数量,不是 50/25/25 权重对应的运行概率,也不会检查 Leaf 是否可达、是否连接 Action 或是否藏在 Group 内

四项 Preview 都是局部检查,真正的结构错误仍需查看当前 Enemy Unit Database 的 Issue Badge

清除 Validation 问题

Enemy 模式的 Issue Badge 扫描当前所选 Enemy Unit Database 中的全部敌人,不只统计正在查看的 Strawman

级别触发条件
ErrorName 为空
ErrorHpMin > HpMax
WarningBehavior 非空且 FlowGraphValidator 返回结构问题

FlowGraphValidator 报告的 Behavior Warning 可以按检查对象归纳为三类

检查范围会报告的问题
节点与标识空或重复 NodeId、不允许用于 Enemy Host 的节点、自定义 Value 节点没有数据输出、Internal Event 或 GES Event 缺少必要标识
连接与端口连接引用不存在的节点或端口、端口类型不兼容、连接元数据与输出端口不一致
Group Body递归检查 Group 内部的同类节点、标识、连接与端口问题

下列内容不会进入 Validation,需要分别在 Preview、FlowGraph Editor 或 Play Mode 中确认

未覆盖范围需要自行检查的边界
Behavior 完整性Behavior 为空、缺少 OnEnemyBehaviorStart、入口未连通、Pattern 无法抵达 Leaf、Leaf 后没有 Action
表现资源与说明缺少 Icon 或 Template、Description 为空、Tags 为空
字段值边界Tier 异常、HpMin < 1

这些 Issue 不会阻止保存、删除或进入 Play Mode,点击 Issue 条目中的 Ping 只会定位到对应敌人、字段或 FlowGraph

结构检查完成后,再用 Used By 确认哪些活动遭遇战直接保存了当前敌人

用 Used By 回到遭遇战

Used By 只扫描当前场景 GameCardManager 已启用的 Encounter Database,并检查 GameEncounter.EnemyUnits 对当前敌人的直接引用

Strawman 的 Used By 显示 The Threshing Field 与 Field of Burning Effigies

The Threshing Field 引用一个 StrawmanField of Burning Effigies 引用两个 Strawman 并搭配一个 Pyre Effigy,同一 Encounter 中的重复引用仍只显示一行 Used By 结果

点击结果会切换到 Encounter 模式并定位对应资产,未启用数据库、其他场景、Prefab、代码引用、GCSApi.SummonEnemy() 与 FlowGraph 的 Summon Enemy 不在扫描范围内

打开 The Threshing Field 后,Enemy Units 会显示 StrawmanNormal Tier 与 14–18 HP,并保留它在敌人阵容中的槽位顺序

The Threshing Field 的 Enemy Units 包含 Strawman、Normal Tier 与 HP 14–18

这项结果确认了 Encounter 对 GameEnemyUnit 的直接引用,Template、随机 HP 与 Behavior 是否真正进入战斗仍需由 Play Mode 验证

在 Play Mode 中验证 Strawman

打开随包场景 1-The Threshing Field 并进入 Play Mode,确认 Strawman 的 Template 已经生成,当前 HP 落在 14–18 范围内

The Threshing Field 的 Play Mode 画面,Strawman 以 15/15 HP 对战 Squire

画面中的 15/15 HP 是 14–18 五个可能结果中的一次有效取值,不是 Strawman 的固定生命,这次运行同时确认随包 Demo 已经加载 The Threshing Field 的敌人阵容、实例化敌人 Prefab 并绑定运行时状态

结束玩家回合后,敌人阶段会执行战斗开始时已经公布的 Leaf,随后规划下一回合意图,运行中的 HP、Armor、状态、Intent 与 Flow 执行可以在 Game Card Monitor 中检查,其余可运行场景见 Demo 场景索引

Play Mode 已经确认这份敌人定义能够进入实际战斗,项目代码需要读取同一份内容或控制运行状态时,则通过 GCSApi 接入

通过 GCSApi 读取敌人内容与运行状态

GameEnemyUnit 保存可复用的敌人定义,Encounter 中的每个非空 Enemy Units 槽位都会创建独立 EnemyUnitState,当前 HP、最大 HP、Armor、状态、死亡标记和已规划意图都保存在运行时状态中,不会回写敌人资产

GCSApi 按内容资产、当前战斗状态、意图和运行时操作提供公开入口

  • 查找敌人内容ActiveEnemyUnitDatabases()EnemyUnits()FindEnemyUnit(guid)
  • 读取战斗单位AliveEnemies()FirstAliveEnemy()EnemyCount()AllUnits()Hp()MaxHp()Armor()HpPercent()IsAlive()IsDead()
  • 读取当前意图CurrentIntentTag()CurrentIntentValue()PendingIntents()
  • 修改敌人状态DealDamage()LoseHp()Heal()SetHp()GainArmor()LoseArmor()SetArmor()KillUnit()ReviveUnit()ApplyStatus()RemoveStatus()ModifyStatusStacks()
  • 运行时召唤SummonEnemy(GameEnemyUnit enemy, UnitState summoner = null)
  • 监听敌人流程OnEnemyTurnStarted()OnEnemyUnitIntentChanged()OnEnemyUnitSummoned()OnEnemyPhaseChanged()OnUnitHpChanged()OnUnitDied()

OnEnemyUnitActing 当前没有独立的强类型快捷方法,需要通过通用的 Subscribe<TArgs>(),并传入 GCSEventNames.OnEnemyUnitActingAction<EnemyUnitActingEventArgs> 完成订阅

GCSApi.Manager 非空时,EnemyUnits() 每次调用都会新建列表并汇总已启用数据库中的敌人,频繁读取时应当缓存结果

没有活动战斗时,AliveEnemies()AllUnits()PendingIntents() 返回空集合,FirstAliveEnemy() 返回 nullEnemyCount() 返回 0

CurrentIntentTag(state)CurrentIntentValue(state) 不依赖当前是否仍有活动战斗,它们会继续读取传入的 EnemyUnitState,只有 statenull 或不是敌人状态时才返回 Unknown-1

各入口的参数、返回值与调用时机见 GCSApi 使用指南,意图与阶段事件的载荷见事件使用指南

Strawman 的 Attack、Defend 与 Multi 现在已经能够在 The Threshing Field 中完成规划与执行

Mire Reaper 图中的 Poison 与 Weak 则需要用 Status 把单次行动延长为跨回合规则,在 Game Card Editor 顶部切换到 Status,按状态创作继续定义这些持续效果