Commit Graph
140 Commits
Author SHA1 Message Date
joywayerandClaude Opus 5 eaba54ea76 feat(ai): Boss 图共享片段 + 竞技场锚点 + AiSignal.Engaged
BossFragments:阶段过渡 / 逼近选招 / 移动到锚点三个静态建态片段。
ApproachAttackEngagement 的建态逻辑提为 internal static Declare(态名参数化),
模块路径与 Boss 图路径共用同一份行为,Boss 可建多组(地面组/空中组)。

锚点坐标经 IBossControl.AnchorAt / DistanceToAnchor 暴露,不走黑板——
EnemyAiBrain._context 是私有的(BossBase 无从写入),且 ResetScratch 会清黑板
带来隐式时序约束。锚点本就是 Boss 专属知识,归 Boss facet 更直。
锚点漏配 / 下标越界显式抛,不回退到自身位置。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 14:32:32 +08:00
joywayerandClaude Opus 5 8c56d207bd feat(enemy): EnemyAbilitySO 补设计备注,命名前缀对齐规范
+ designNote(目标体量下能力数量大,设计意图需就近记录)。
fileName 由 EAB_ 改为 ABL_——AssetFolderSpec 第 298 行、两个向导
以及 PlayClipAbilitySO 等子类都用 ABL_,此前只有基类是 EAB_。
顺带清掉 abilityId 注释里的旧插件残留字样。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 14:23:41 +08:00
joywayer 50f505279d feat(enemy): BossPhaseAbilityGate——阶段即换招池
按阶段启停能力组件,被禁用的招经 CanUse 自动退出选招候选,
阶段门不需要碰选招器。取代 BossSkillSO.availablePhaseIndices。
EnterPhase 先换池后广播;OnSpawn 回阶段 0(对象池复用)。
2026-07-30 13:50:34 +08:00
joywayer 64d2087adc fix(enemy): 禁用的能力组件不再报告可用
CanUse 纳入 enabled。此前禁用组件仍返回 true,选招器会选中一个
StartCoroutine 必然失败的招。这也是阶段门(按阶段启停能力)的前提。
2026-07-30 13:28:23 +08:00
joywayerandClaude Opus 5 0a92d21ce1 fix(enemy): 应用 Task 3 代码审查意见
补上池化路径的防重复记忆重置——ResetRepeatMemory 此前文档承诺了
「对象池复用时清除」却无任何调用点,而它要取代的 BossBase.LastUsedSkillId
恰好在 OnSpawn 里有重置。放 EnemyBase.OnSpawn 以覆盖全部池化敌人。

折扣系数改为每次选招前刷新,与 attackSelectionMode 的读取时机对齐——
此前策划在播放模式下调系数无效、调模式却立即生效,容易误判为功能没生效。
默认值收敛为 EnemyAttackSelector.DefaultAntiRepeatFactor 单一常量。

测试:IneligiblePrevious 用例改用系数 0.5——原先用 0 时,把折扣错写在
eligibility 归零之前也照样通过,是个永远不会失败的测试;统计用例边界由
7σ 收紧到 5σ 使其真正验证该系数;补 ResetRepeatMemory 的确定性用例、
系数 1.0 无惩罚、三候选三条。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 13:00:28 +08:00
joywayerandClaude Opus 5 eb3f4888a4 feat(enemy): 选招器支持防重复折扣——WeightedRandomAntiRepeat
上一次选中的招按 EnemyStatsSO.attackAntiRepeatFactor 折扣权重(默认 0.3)。
折扣把唯一候选压到 0 时退化为 Priority 路径,不会出现敌人永不出手。
阶段切换清空防重复记忆。取代 BossBase.UseBossSkillWeighted 里的同名逻辑。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 12:43:01 +08:00
joywayerandClaude Opus 5 2a1ada4388 fix(ai): 应用 Task 1+2 代码审查意见
ResourceFull 未挂 BossResource 时改为显式抛——原先静默返回 false,
是 CLAUDE.md 第 6 条禁止的下游兜底,且与紧邻的 Boss facet 行为不一致。
FakeBossControl.DistanceToAnchor 不再忽略 index。测试改用 TearDown 清理
(本项目关闭了 Domain/Scene Reload,失败断言会把物体永久留在打开的场景里)。
BeginPhaseTransition 去掉死的默认参数;接口补充重入契约说明。

顺带去重:FakeAiContext 实现 IEnemyActor,删除两个测试内的本地 Ctx 副本
——一个接口成员改动要同步三份是复发性成本。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 12:31:39 +08:00
joywayerandClaude Opus 5 3665504a58 feat(ai): 新增 IBossControl facet——Boss 阶段状态经 IAiContext 供图读取
非 Boss 敌人访问 IAiContext.Boss 显式抛 InvalidOperationException,
不返回空对象掩盖小怪图误挂 Boss 边的错误。BossResource 补 IsFull 供图条件边判定。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 12:15:54 +08:00
joywayer afcc0b10ee fix(enemy): 配方校验改用一次性 builder 探测,不再干扰共享图缓存 2026-07-30 08:33:53 +08:00
joywayer da217af113 feat(enemy): AI 配方接入 SO 校验——漏配/歧义/零冷却 Committed 在编辑期与构建期报错 2026-07-29 17:20:12 +08:00
joywayer 6df4a259b7 docs(enemy): 修正作者指南与两处注释残留的死亡层表述 2026-07-29 16:34:21 +08:00
joywayer 44412adfc7 refactor(enemy): E001 AI 迁移为配方资产,退役定制脚本
用 EnemyAiRecipeWizard 建 ENM_E001_Ai.asset,配置未发现层
DisguiseThenPatrol + 交战层 RushEngagement(e001_chase, Committed);
TestRoomA 场景 EnemyAiBrain 改绑 _recipe,_definitionId 清空;
删除 E001CaoZhiAi.cs;SceneObjectPlacerTool 的 E001 挂载分支与其余
AI(BrainGraph) 提示文案统一改为指向配方向导路径。
2026-07-29 15:38:44 +08:00
joywayer ecdb0040cb feat(editor): 敌人 AI 配方脚手架向导;AssignModules 改名并失效缓存
- AiRecipeSO 新增 protected InvalidateGraph(),子类装配模块后调用以丢弃缓存图,
  避免改动要等到下次进 Play 才生效的静默陈旧图问题。
- PerceptionRecipeSO.SetModulesForTests 改名为 AssignModules(向导也要用它装配模块,
  旧名字具有误导性),并在装配后调用 InvalidateGraph。
- 新增 EnemyAiRecipeWizard:按 AssetFolderSpec 定名定路径创建感知型 AI 配方资产
  (Assets/_Game/Data/Enemies/{EnemyID}/ENM_{EnemyID}_Ai.asset),已存在则选中不覆盖。
- PerceptionRecipeSoTests 同步改名调用点,并新增测试钉住"装配后缓存必须失效"契约。
2026-07-29 15:28:25 +08:00
joywayer 426fa3601d fix(enemy): EnemyAiBrain 配置守卫不随重新启用蒸发,注册表消重 2026-07-29 15:23:49 +08:00
joywayer 57cbaacf2c feat(enemy): EnemyAiBrain 支持配方资产/AiScript id 二选一解析 2026-07-29 14:56:54 +08:00
joywayer 825cae7977 feat(enemy): PerceptionRecipeSO 配方资产 + SubclassSelector 模块下拉
未发现层/交战层各用 [SerializeReference]+[SubclassSelector] 下拉挑选模块,
新增模块类自动出现在下拉里,无需改枚举或已有文件。默认交战模块仍为
RushEngagement——未配能力时建图必须显式报错,而非静默产出打不出手的图。
2026-07-29 14:46:41 +08:00
joywayer 7327a5fe09 refactor(enemy): 退役 PerceptionStateMachine,E001 切换到两层模块组装 2026-07-29 14:24:48 +08:00
joywayer bf8101b3f5 feat(enemy): PerceptionSkeleton——两层可插拔的感知骨架,自声明死亡终态 2026-07-29 14:10:46 +08:00
joywayer faa210c789 revert(enemy): 收掉死亡层——死亡归物理层,AI 只需一个终态 2026-07-29 14:02:13 +08:00
joywayer 5a9c1fd569 chore(enemy): 补齐死亡层模块的 .meta 文件 2026-07-29 13:46:45 +08:00
joywayer 3bc7eb1855 feat(enemy): 死亡层三模块(终态/单段/两段) 2026-07-29 13:46:20 +08:00
joywayer 3d00c66677 test(enemy): 补测 Attack 单出边的自愈路径,写明边序依赖的射程前提
Approach 边序注释:attackInRange 先于 leftAllZones 的前提是攻击射程恒小于
感知区(EnemyAttackSelector.Eligible 的 InAttackRange 门),故两条件不会相争;
若未来出现射程更大的招式,应由 AI 配方校验器报错,而非靠调边序绕开。

FakeCombat 新增 BestAttackFails 开关(与 Eligible 解耦),补测 Attack 唯一出边
attackDone 的自愈不变量:UseBestAttack 触发失败时不留下运行中能力,下一帧即可
自愈回 Approach,不会永久卡死。
2026-07-29 13:08:46 +08:00
joywayer 9d632cd103 fix(enemy): 退回 Approach 边序——脱战优先属假件失真,改由测试贴合真实射程语义
HasEligibleAttack() 只看攻击射程圆(远小于追击/视野区),脱离全部感知区在真实系统里
必然已脱离攻击射程,原顺序(attackInRange 先于 leftAllZones)本就正确。
FakeCombat.Eligible 是裸字段不会随 Chase/Vision 联动,才让上一版看似需要调边序。
改法:边序退回原样,测试里玩家离开感知区时手工同步清 Eligible,贴合真实耦合关系。
2026-07-29 12:59:07 +08:00
joywayer a700bef352 feat(enemy): ApproachAttackEngagement——攻击改为起手即打完,不中途收招
寻路逼近↔到射程选招攻击的交战模块。招式射程/冷却/权重归 EnemyAttackSelector,
本模块只决定何时逼近、何时出手。

有意的行为变更:Attack 态去掉 leftAllZones 边,玩家在前摇中跑出感知区不再
中途打断招式,招式完整打完后经 Approach 自然脱战。
2026-07-29 12:53:49 +08:00
joywayer 5771ac414e test(enemy): 补测 Committed 冲锋的防抖动闭环,RushExit 写明冷却前提 2026-07-29 12:45:43 +08:00
joywayer bb1e2f7705 feat(enemy): RushEngagement——两个耦合 flag 合并为 RushExit 语义枚举 2026-07-29 12:32:50 +08:00
joywayer acfba66c5d feat(enemy): 未发现层三模块(单一态/单向降级/定时交替) 2026-07-29 12:19:26 +08:00
joywayer 80fdc36762 feat(ai): BrainBuilder.DeclareState——重复声明状态即报错,防模块间同名静默覆盖
State() 仍保持宽松(有则取),用于给已声明的态挂边;DeclareState() 只用于
首次声明行为,重复声明同名状态会抛异常。AiStateFragments 的四个建态原语
(Locomotion/Ability/AbilityOnce/Terminal)改用 DeclareState。同时给
IEngagementModule/IDeathModule/IUnawareModule 补充不变量说明。
2026-07-29 12:01:19 +08:00
joywayer 17e71dac39 feat(enemy): 未发现层/交战层/死亡层三个模块契约 2026-07-29 11:47:29 +08:00
joywayer 68f615e9c1 fix(enemy): AiStateFragments 空能力 id 建图期报错,补 OnExit 收尾测试
Ability/AbilityOnce 建图期校验 abilityId 非空,与 BrainBuilder.RequireState
同一类"漏配即快速失败"约束保持一致,避免定制 AiScript 漏配 id 时产出静默
不作为的状态。同时补 4 个测试:Locomotion/Ability 的 OnExit 收尾行为,以及
两个原语对空 id 的报错行为。
2026-07-29 11:42:47 +08:00
joywayer 77a32cbf8a feat(enemy): AiStateFragments 建态原语,新增 AbilityOnce 修死亡态重触发隐患
从 PerceptionStateMachine 的 private static 辅助方法提升为公开原语,供后续
模块化重构(骨架+可插拔模块)与定制 AiScript 复用。新增 AbilityOnce:
只在进入时触发能力、不每帧重触发,修复用 Ability() 驱动死亡态时演出播完
被 Tick 无限重播的隐患(现有 PerceptionStateMachine 因 E001 死亡能力 id
为空未暴露,本次不改它,留待 T11 整体退役)。
2026-07-29 11:35:47 +08:00
joywayer 474e89de3a feat(enemy): AbilityRef——AI 层能力引用资产化,字符串仅作定制脚本兜底 2026-07-29 11:22:15 +08:00
joywayer c4e80afe9e chore(enemy): 清除随寻路库失效的 NavDriving 死代码与两处过时注释
NavDriving 原由已删除的寻路适配层设置,现无人写入(全项目 C# 零引用),
连同其调试字段一并移除;场景/预制体里的序列化残值由 Unity 下次保存自动丢弃。
2026-07-28 13:28:52 +08:00
joywayer a220b5c0d8 删除多余 2026-07-28 13:18:41 +08:00
joywayer 3c622a69f2 refactor(enemy): NavLinkType 迁入 INavLinkHandler 并改述为能力驱动的地形穿越;补交新脚本 .meta 2026-07-28 11:50:17 +08:00
joywayer 4455062ee9 refactor(editor): 脚手架改用 GroundNavigator,移除寻路库引用与导航面放置工具 2026-07-28 11:45:24 +08:00
joywayer 219fe46719 fix(enemy): GroundNavigator 停止改为直写移动输入,消除与 EnemyBase.StopMovement 的无限递归(栈溢出) 2026-07-28 11:39:25 +08:00
joywayer de3c9deff4 refactor(enemy): 消费者切换到 IEnemyNavigator(Wander/Waypoints 去导航图化,调试面板简化) 2026-07-28 11:25:21 +08:00
joywayer 49627d357d refactor(enemy): FlyingDirectNavigator 改名 FlyingNavigator 并切换到 IEnemyNavigator 2026-07-28 11:17:34 +08:00
joywayer 668bc3500e feat(enemy): 新增 GroundNavigator 地面直接移动导航(+7 纯函数单测)
补充 EditMode 测试程序集对 BaseGames.Enemies.Navigation 的引用(此前缺失,新测试无法编译)
2026-07-28 11:12:11 +08:00
joywayer 2174e42ce0 feat(enemy): 新增 IEnemyNavigator 瘦身导航接口(7 成员)与 NullEnemyNavigator 2026-07-28 11:07:53 +08:00
joywayer 8ea919a7f1 chore(enemy): 补交 StallDetector 与其测试的 .meta 2026-07-28 11:07:06 +08:00
joywayer c929b5efb7 refactor(enemy): 三处卡死检测收敛为 StallDetector;修复 Pace 持续受阻时无法掉头的死锁 2026-07-28 11:04:18 +08:00
joywayer 5cfacf199a feat(enemy): 新增 StallDetector 推进停滞检测(+8 单测),为收敛三处重复实现做准备 2026-07-28 11:01:01 +08:00
joywayer 28cd335f40 chore(enemy): [临时调试] E001 出生即巡逻,用于真机验证中心悬空导致导航失效的问题
代码处已留 [临时调试] 标记,验证结束后改回 Entry=Idle_Disguise。
2026-07-27 16:01:03 +08:00
joywayer 47c2ce7e99 fix(enemy): 冲锋禁止以中心悬空姿态收尾(会导致导航映射失败/巡逻失效)
新增 EnemyMovement.IsCenterOverGround() 与 RushAbility.SettleRoutine:
冲锋结束时若着地却中心悬在崖外,继续朝原方向推进直到离地(自由落体)或中心重回地面上方;
有时限,超时仍未脱离则告警暴露地形问题(崖沿有墙),不静默留下坏站位。
2026-07-27 15:50:01 +08:00
joywayer 80c0e5c277 revert(enemy): E001 初始态改回 Idle_Disguise(伪装静止),移除临时调试改动 2026-07-27 15:27:15 +08:00
joywayer 4808077fc6 feat(enemy): ContactChaseAbility 改造为 RushAbility(冲锋)
- 起手前锁定玩家 X 与方向(committed),终点改为身体整体越过锁定点(Body.HasPassed)
- 终止条件:越过锁定点/撞墙(只判墙)/最大冲刺时长(SO 新增 maxDashDuration)/净位移卡死
- 冲锋期间经 EnemyMoveInput.AllowLedgeCross 放开悬崖夹紧,可冲下崖不悬停边缘
- 类与文件重命名(GUID 保留),脚手架与向导同步更新
2026-07-27 13:38:05 +08:00
joywayer 9f8d4f21ca fix(enemy): EnemyMovement 加 RequireComponent(EnemyBase),固化身体权威同物体不变量 2026-07-27 12:13:10 +08:00
joywayer b1d3c169ec chore(enemy): 补交 EnemyBody 与其测试的 .meta 2026-07-27 12:07:46 +08:00