《小匕首》中战斗管线的实现
源码路径:
Assets/_Project/Scripts/Tatakai
设计参考:Assets/_Project/Scripts/Tatakai/战斗文档.md
生成日期:2026-06-15
目录
- 模块总览
- 战斗生命周期
- 回合流程详解
- 行为管线与时点序列
- Buff 系统
- BattleContext 上下文
- TatakaiManager 调度中枢
- 地块、染色与召唤物
- 骰子生命周期
- 敌人意图与 AI
- 设计文档与代码对照
- 文件索引
一、模块总览
1.1 目录结构
1 | Tatakai/ |
1.2 核心架构
1 | ┌─────────────────────────────────────────────────────────────┐ |
关键原则:
- 所有战斗行为都通过 时点(BuffTriggerPoint) 驱动 Buff 结算
- Buff 只读写
BattleContext,不直接碰实体 - 需要改游戏状态的副作用入
PendingOps,由 Manager 统一消费 ActionPipeline定义「一种行为要经过哪些时点」;TatakaiManager负责在正确时机调用
二、战斗生命周期
2.1 战斗目标
- 玩家失败:主角 HP 归零
- 玩家胜利:所有怪物死亡
2.2 初始化流程
入口: SetupBattle()(正式战斗)或 InitDefault()(测试场景)
1 | SetupBattle(player, enemy, dices, buffs, addedTiles) |
2.3 战斗结束
死亡事件触发后(_battleResolved 防重入):
1 | Exec(Death) → 玩家 + 敌人 |
三、回合流程详解
3.1 完整回合循环
1 | ┌──────────────────────────────────────────────────────────────┐ |
3.2 玩家回合开始 StartRound()
| 步骤 | 代码行为 | Buff 时点 |
|---|---|---|
| 1 | RegenerateDiceFromTemplate():保留上回合 retained 骰子 + 按模板新发 + 每颗触发 |
DieAcquired(每颗新骰) |
| 2 | ShuffleBoard():随机洗牌地块顺序 |
— |
| 3 | DecideEnemyIntent():决定敌人下回合意图 |
— |
| 4 | _player.ClearDefense():清空玩家护盾 |
— |
| 5 | 重置跨回合追踪变量 | — |
| 6 | _roundNumber++ |
— |
| 7 | 护盾清零时点 | ShieldCleared(玩家) |
| 8 | 回合开始 Buff | TurnStart(玩家 + 敌人) |
| 9 | 遍历棋盘召唤物 | SummonTurnStart + SummonDamage 管线(若有伤害) |
| 10 | 召唤物 Tick(),归零则移除 |
— |
跨回合追踪变量(FillCommonContext 写入 ctx):
| 变量 | 用途 |
|---|---|
_roundNumber |
每 N 回合类 Buff(进化等) |
_playerDealtDamageThisTurn |
饥饿 Buff |
_firstFleshUsedThisTurn |
血肉首击 Buff |
_consecutiveSameValueCount |
同点数连击类 Buff |
_previousDieValue |
连珠炮等递增判定 |
3.3 玩家行为
A. 移动 TryMove(dieIndex, targetIndex)
前置校验: 玩家回合、骰子有效、目标格 = 左/右折返可达位置
时点序列(Manager 手写,非完整 ActionPipeline):
1 | UseDie |
折返算法: BounceMove(start, steps, boardSize) — 碰边折返,超过 10 格表现层加速(Buff 照常触发)
B. 触发地块 TryActivateTile(dieIndex)
前置校验:
- 骰子颜色与地块颜色兼容(
tile.Color.CanActivateBy(die.Color)) 点数必须大于本格已用最高点数(已移除,反馈#6)
连击叠层: 同地块 die.CurrentValue > tile.HighestDieUsed 且 HighestDieUsed > 0 → GrantCombo()
| 地块类型 | 调用 | 管线 |
|---|---|---|
TileType.Attack |
ExecuteAttackAction() |
ActionPipeline.PlayerAttack |
TileType.Defend |
ExecuteDefendAction() |
ActionPipeline.PlayerDefend |
攻击后结算:
1 | PlayerAttack 管线 → DrainPendingOps |
防御后结算:
1 | PlayerDefend 管线 → DrainPendingOps |
C. 结束回合 EndTurn() → EndPlayerTurn()
1 | TurnEnd(玩家) |
注意: 玩家 Buff 的
TickBuffs()不在EndPlayerTurn中执行,而是移到敌人攻击之后,确保「脆弱」等受击 Buff 对本回合敌人攻击仍生效。
3.4 敌人回合 EnemyTurnRoutine()
1 | _turnState = EnemyTurn |
四、行为管线与时点序列
4.1 ActionPipeline 机制
文件:Buff/ActionPipeline.cs
每个行为 = 有序的 ActionPipelineStep[],每步指定:
BuffTriggerPoint:触发哪个时点PipelineMode:Single(只跑源实体)或Dual(源 + 目标都跑)
Dual 模式执行顺序:
1 | ctx.IsRunningOnTarget = false; |
4.2 预定义管线对照表
玩家攻击 PlayerAttack
| 序号 | 时点 | 模式 | 跑 Buff 的实体 | 典型效果 |
|---|---|---|---|---|
| 1 | UseDie |
Single | 玩家 | 独角、种子心脏、狂乱 |
| 2 | ActivateTile |
Single | 玩家 | 骰子颜色虚弱 |
| 3 | Attack |
Dual | 玩家→敌人 | 强壮(+伤害)、初始脑袋 |
| 4 | Hit |
Dual | 玩家→敌人 | 触手2、施加脆弱 |
| 5 | DealDamage |
Single | 玩家 | 虚弱(-50%伤害)、吸血 |
| 6 | HitTaken |
Single | 玩家 | — |
| 7 | DamageTaken |
Dual | 敌人→玩家 | 脆弱(+50%受伤)、藤蔓身体 |
结算时机: 管线跑完后 _enemy.TakeDamage(ctx.FinalDamage)
玩家防御 PlayerDefend
| 序号 | 时点 | 模式 | 典型效果 |
|---|---|---|---|
| 1 | UseDie |
Single | — |
| 2 | ActivateTile |
Single | 骰子颜色虚弱 |
| 3 | Defend |
Single | 敏捷(+护盾)、启示 |
| 4 | GainShield |
Single | 木头脑袋(低点点数翻倍) |
结算时机: _player.AddDefense(ctx.ShieldAmount)
玩家移动(Manager 手写,管线仅定义前 4 步)
| 时点 | 触发位置 | 典型效果 |
|---|---|---|
UseDie |
TryMove 开头 | — |
Move |
TryMove | 移动回复(Haste) |
PassTile |
逐格循环 | 路径免疫 |
EnterTile |
最后一格 | 吸盘、叶之翼、疤痕 |
怪物攻击 EnemyAttack
| 序号 | 时点 | 模式 | 说明 |
|---|---|---|---|
| 1 | Attack |
Dual | 敌人强壮 + 玩家(若有攻击相关) |
| 2 | Hit |
Dual | — |
| 3 | DealDamage |
Single | 敌人虚弱 |
| 4 | HitTaken |
Single | 玩家荆棘 |
| 5 | DamageTaken |
Dual | 玩家脆弱/裂隙之中 |
怪物攻击不含 UseDie、ActivateTile、DyeTile(与设计文档一致)
怪物防御 EnemyDefend
| 时点 | 典型效果 |
|---|---|
Defend |
敌人敏捷 |
GainShield |
— |
召唤物伤害 SummonDamage
| 时点 | 说明 |
|---|---|
DealDamage |
— |
HitTaken |
— |
DamageTaken |
玩家受伤类 Buff |
4.3 染色时点(攻击/防御后单独触发)
1 | TryDyeTile(die, tile, ctx) |
4.4 完整时点枚举
文件:Buff/BuffTriggerPoint.cs
行为管道:
UseDie → Move → PassTile → EnterTile → ActivateTile → Attack → Hit → DealDamage → HitTaken → DamageTaken → Defend → GainShield → DyeTile → EatFood
回合/骰子/战斗:
TurnStart / TurnEnd / ShieldCleared / DieDiscarded / DieRetained / DieDestroyed / DieUpgraded / DieRerolled / DieAcquired / BattleStart / BattleEnd / Death / SummonTurnStart / SummonTurnEnd
待定: BuffGained / BuffApplied / SummonCreated
五、Buff 系统
5.1 三层结构
1 | IBuff(模板接口) |
5.2 BuffPipeline 执行规则
文件:Buff/BuffPipeline.cs
1 | 筛选:!IsExpired && TriggerPoint 匹配 && Condition(ctx) 通过 |
5.3 三种 Buff 实现
| 方式 | 入口 | 适用场景 |
|---|---|---|
| BuffCatalog | BuffCatalog.Create("强壮") |
游戏内主要 Buff,中英键名 |
| SO 数据驱动 | SO_BuffData.ToBuff() → ScriptableBuff |
策划配置简单数值效果 |
| CombatBuffFactory | CombatBuffFactory.Create(CombatBuffId) |
肢体/装备枚举 ID |
SO 回退规则: SO_BuffData.effects 为空时,按 buffName 查 BuffCatalog(SO 仅作元数据壳)。
5.4 层数与持续时间
| 类型 | StacksAreDuration |
Tick 行为 | 叠层规则 |
|---|---|---|---|
| 强壮/敏捷/虚弱/脆弱 | true |
层数 = 剩余回合,同步衰减 | 叠层后 RemainingDuration = Stacks |
| 连击/永久类 | false |
只减 RemainingDuration | 层数独立累加 |
BuffInstance.GrantInto() 是统一的施加/叠层入口(Manager 和测试共用)。
5.5 副作用延迟队列
Buff 执行中不能直接改实体,通过 BattleContext.PendingOps 入队:
| API | PendingOpKind | Manager 消费 |
|---|---|---|
GrantSelf/GrantOpponent |
GrantBuff | BuffCatalog + GrantInto |
QueueAddDice |
AddDice | AddDice() → DieAcquired |
QueueSelfDamage |
SelfDamage | LoseHp(不触发 Buff) |
QueueHeal |
Heal | Heal() |
QueueGainShield |
GainShield | AddDefense() |
QueueRemoveDie |
RemoveDie | 从池移除 |
QueueRerollDie |
RerollDie | RerollDie() → DieRerolled |
直接改骰子(不走队列): die.Upgrade() / die.Retain() — Manager 通过快照补发 DieUpgraded / DieRetained。
5.6 代表性 Buff 与时点映射
| Buff | 时点 | 条件要点 | 效果 |
|---|---|---|---|
| 强壮 | Attack | 攻击方 !IsRunningOnTarget |
FinalDamage += 层数 |
| 敏捷 | Defend | IsDefense | ShieldAmount += 层数 |
| 虚弱 | DealDamage | 攻击方 | FinalDamage -= 50% |
| 脆弱 | DamageTaken | 受击方 IsRunningOnTarget |
FinalDamage += 50% |
| 连击(攻击) | Attack | IsAttack | FinalDamage += 层数 |
| 饥饿 | TurnEnd | 本回合未造成伤害 | QueueSelfDamage(5) |
| 藤蔓身体 | DamageTaken | 受击 & 伤害≥5 | 每 5 点伤获得 1 个植物 d4 |
| 触手2 | Hit | 血肉攻击 | 伤害×2,OneShot 失效 |
| 进化 | TurnStart | 每 3 回合 | GrantSelf 永久强壮/敏捷 |
六、BattleContext 上下文
文件:Core/BattleContext.cs
6.1 字段分组
骰子: UsedDie, DieIndex, DieColor
地块: SourceTileIndex, TargetTileIndex, TargetTile, Board
数值: BaseDamage, FinalDamage, HealAmount, ShieldAmount
行为标记: IsAttack, IsDefense, IsMove, IsTileAction, IsEnemyAction, IsSummonAction, IsCancelled
Buff 基建: CurrentStacks, CurrentOwner, IsRunningOnTarget, RoundNumber, PlayerDealtDamageThisTurn, PendingOps
染色: PreviousTileColor, NewTileColor
追踪: ConsecutiveSameValueCount, PreviousDieValue, IsFirstFleshUseInTurn, IsOverflowHeal
6.2 工厂方法
1 | BattleContext.ForAttack(die, tileIndex, baseDamage, isEnemyAction) |
七、TatakaiManager 调度中枢
7.1 两种 Buff 触发入口
| 入口 | 用途 | 是否 DrainPendingOps | 是否补发骰子时点 |
|---|---|---|---|
Exec(triggerPoint, ctx, entity) |
单时点(回合开始、弃骰等) | ✅ | ✅(快照对比) |
ActionPipeline.X.Execute(ctx, src, tgt) |
行为管线(攻击/防御) | 管线后手动调用 | ❌(管线内逐步 Exec 时由外层控制) |
Exec() 内部流程:
1 | 拍骰子池快照(UpgradeCount / IsRetained) |
7.2 意图预览(Dry-Run)
敌人意图 UI 显示「含 Buff 后的预期值」:
1 | PreviewEnemyAttack(baseDamage): |
7.3 连击 Buff 管理(Manager 特化逻辑)
不在 BuffCatalog 的 Tick 流程中,由 Manager 直接操作:
- 叠层: 同地块用更大点数骰子 →
GrantCombo(isAttack) - 清零: 移动时
ResetCombo()移除连击(攻击)/连击(防御)
7.4 Buff Tick 时机(重要实现细节)
| 实体 | Tick 时机 | 原因 |
|---|---|---|
| 敌人 | 敌人 TurnEnd 后 | 标准回合衰减 |
| 玩家 | 敌人攻击后、ApplyIntentBuffs 前 | 确保脆弱等对本次攻击生效;新意图 Buff 不被立刻 Tick 掉 |
八、地块、染色与召唤物
8.1 地块 Stage
| 字段 | 说明 |
|---|---|
TileType |
Attack / Defend |
Color |
TileColor(支持单色/双色) |
Summon |
召唤物数据 |
HighestDieUsed |
本格已用最高骰点(移动经过时重置为 0) |
ResetByMove |
是否被移动刷新 |
8.2 染色规则 TileColor
文件:Core/TileColor.cs
- 触发染色: 骰子颜色 ⊄ 地块颜色 →
DyedBy(dieColor) - 不染色: 骰子颜色已是地块主色或副色之一
- 多彩兼容单彩: 血肉+植物格子上,血肉骰子可触发效果
8.3 召唤物 SummonData
| 效果字段 | 触发时机 | 是否走 Buff |
|---|---|---|
OnTurnStartDamage |
玩家回合开始 | SummonDamage 管线 + 直接 TakeDamage |
OnPassDamage |
移动经过 | 直接 LoseHp |
OnEnterDamage |
移动进入 | 直接 LoseHp + 移除召唤物 |
OnEndTurnShield |
玩家回合结束站在同格 | 直接 AddDefense |
Duration |
每回合开始 Tick | 归零移除 |
设计文档:「失去生命值」不触发 Buff — 代码中
LoseHp()直接扣血,不走管线。
九、骰子生命周期
9.1 每回合发牌 RegenerateDiceFromTemplate()
1 | 保留上回合 retained 骰子(原样带入,不重摇) |
9.2 骰子时点补发机制
Buff 中直接调用 die.Upgrade() / die.Retain() 不会自动触发时点。Exec() 通过快照对比补发:
| 检测 | 补发时点 |
|---|---|
UpgradeCount 增加 |
DieUpgraded |
IsRetained false→true |
DieRetained |
9.3 弃置与保留
回合结束:
IsRetained == true→ClearRetain(),保留在池中带入下回合- 否则 →
Exec(DieDiscarded)→ 从池移除
回合结束自动弃置的骰子不算 DieDiscarded 的设计意图在代码中:未保留的骰子会触发 DieDiscarded。
9.4 手牌排序
SortDicePool():颜色 → 点数升序 → 面数
十、敌人意图与 AI
10.1 意图决定 DecideEnemyIntent()
优先级:
- 脚本意图(
scriptedIntents):教学敌人按回合顺序 - 强制攻击:第 1 回合必攻击;上回合 Special 意图 → 本回合必攻击
- 意图池:条件意图(按 priority)→ 加权随机
- 兜底:50% 随机攻/防 + Inspector 固定值
10.2 条件意图
| IntentCondition | 判定 |
|---|---|
FirstTurn |
_enemyTurnCount == 1 |
HpBelowValue |
当前 HP ≤ conditionValue |
HpBelowPercent |
HP 比例 ≤ conditionValue |
10.3 意图执行 ExecuteEnemyIntentRoutine()
1 | 有 damage → ExecuteEnemyAttack(EnemyAttack 管线) → TakeDamage |
10.4 意图 Buff 施加
1 | AddIntentBuff(target, BuffPayload): |
与 GrantInto 不同:意图 Buff 不合并叠层,直接 Add 新实例。
十一、设计文档与代码对照
| 设计文档 | 代码实现 | 差异 |
|---|---|---|
| 同地块点数递增才能再触发 | HighestDieUsed 仍记录 | 门槛已移除(反馈#6) |
| 玩家攻击含染色时点 | PlayerAttack 管线后 TryDyeTile | ✅ 一致 |
| 怪物攻击不含 UseDie/ActivateTile | EnemyAttack 从 Attack 开始 | ✅ 一致 |
| 失去生命值不触发 Buff | LoseHp() 直接扣血 |
✅ 一致 |
| 回合结束 Buff 持续时间-1 | TickBuffs() | 玩家 Tick 推迟到敌人攻击后 |
| 层数即持续时间型 Buff | StacksAreDuration | ✅ 已实现 |
| 获得 buff 时点 | BuffGained | 待定/占位 |
| 召唤物移动 | MovePerTurn | 字段存在,移动逻辑未实现 |
十二、文件索引
核心逻辑
| 文件 | 职责 |
|---|---|
TatakaiManager.cs |
战斗中枢:回合、行为、Buff 调度、敌人 AI |
Buff/ActionPipeline.cs |
行为→时点序列定义 |
Buff/BuffPipeline.cs |
单时点 Buff 筛选与执行 |
Buff/BuffTriggerPoint.cs |
全部时点枚举 |
Core/BattleContext.cs |
行动上下文 + 副作用 API |
Core/PendingBuffOp.cs |
副作用队列数据结构 |
Buff/BuffInstance.cs |
运行时 Buff + GrantInto |
Buff/Buffs/BuffCatalog.cs |
主要 Buff 实现注册表 |
实体与场景
| 文件 | 职责 |
|---|---|
Core/Character.cs |
玩家:HP/护盾/Buff/TakeDamage/LoseHp |
Core/Enemy.cs |
敌人:同上 |
Core/ICombatEntity.cs |
战斗实体接口 |
Core/Stage.cs |
地块 |
Core/TileColor.cs |
染色逻辑 |
Core/SummonData.cs |
召唤物 |
表现层(不参与逻辑结算)
| 文件 | 职责 |
|---|---|
Fronts/TatakaiFrontend.cs |
前端总控 |
Fronts/StageBoard3D.* |
3D 棋盘、移动、交互 |
Fronts/BattleHud.cs |
战斗 HUD |
Fronts/EnemyIntentView.cs |
敌人意图显示 |
Fronts/BuffRowView.cs / BuffTooltip.cs |
Buff UI |
测试
| 文件 | 职责 |
|---|---|
EnemySystem/Test/BattleIntegrationTest.cs |
管线集成测试 |
附录:玩家攻击完整时序图
1 | 玩家拖骰子到怪物 → TryActivateTile |
本文档基于源码静态分析生成,若后续改动 TatakaiManager 或 ActionPipeline,请以代码为准同步更新。
- Title: 《小匕首》中战斗管线的实现
- Author: Seagull OO
- Created at : 2026-06-15 18:55:22
- Updated at : 2026-06-16 10:35:09
- Link: https://seagulloo.cn/2026/06/15/小匕首中战斗管线的实现/
- License: This work is licensed under CC BY-NC-SA 4.0.