diff --git a/Assets/_Game/Data/Enemies/E001/ENM_E001_Ai.asset b/Assets/_Game/Data/Enemies/E001/ENM_E001_Ai.asset new file mode 100644 index 00000000..95ba18fa --- /dev/null +++ b/Assets/_Game/Data/Enemies/E001/ENM_E001_Ai.asset @@ -0,0 +1,32 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0b849b67f708c3b4f9af91a9e5f2e546, type: 3} + m_Name: ENM_E001_Ai + m_EditorClassIdentifier: + _unaware: + rid: 2385399935748276230 + _engagement: + rid: 2385399935748276231 + references: + version: 2 + RefIds: + - rid: 2385399935748276230 + type: {class: DisguiseThenPatrol, ns: BaseGames.Enemies, asm: BaseGames.Enemies} + data: + _disguiseMode: 0 + _patrolMode: 1 + - rid: 2385399935748276231 + type: {class: RushEngagement, ns: BaseGames.Enemies, asm: BaseGames.Enemies} + data: + _ability: + _asset: {fileID: 11400000, guid: 0adeaa8a8508fbd40986dbb71cc85acd, type: 2} + _exit: 1 diff --git a/Assets/_Game/Scripts/Enemies/AIBrain/Ai.meta b/Assets/_Game/Data/Enemies/E001/ENM_E001_Ai.asset.meta similarity index 52% rename from Assets/_Game/Scripts/Enemies/AIBrain/Ai.meta rename to Assets/_Game/Data/Enemies/E001/ENM_E001_Ai.asset.meta index 93649e8b..42c51aa5 100644 --- a/Assets/_Game/Scripts/Enemies/AIBrain/Ai.meta +++ b/Assets/_Game/Data/Enemies/E001/ENM_E001_Ai.asset.meta @@ -1,8 +1,8 @@ fileFormatVersion: 2 -guid: d0934d78d9f1fe34aa6c0429a0822df8 -folderAsset: yes -DefaultImporter: +guid: ec998c8e30b9c514d81b67da92c6d42a +NativeFormatImporter: externalObjects: {} + mainObjectFileID: 11400000 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/_Game/Scenes/Testings/TestRoomA.unity b/Assets/_Game/Scenes/Testings/TestRoomA.unity index 736a0ea2..ec2ee748 100644 --- a/Assets/_Game/Scenes/Testings/TestRoomA.unity +++ b/Assets/_Game/Scenes/Testings/TestRoomA.unity @@ -5403,7 +5403,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d92d657c6bbdfe246a7333e04f79f8f7, type: 3} m_Name: m_EditorClassIdentifier: - _definitionId: E001 + _recipe: {fileID: 11400000, guid: ec998c8e30b9c514d81b67da92c6d42a, type: 2} + _definitionId: --- !u!114 &310446317 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs b/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs index 0d342133..b7ebec27 100644 --- a/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs +++ b/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs @@ -338,8 +338,9 @@ namespace BaseGames.Editor SetupPerceptionSystemSlots(sensorHub, new[] { "aggro", "los" }, report); report.Add("★ 指定 EnemyBase._statsSO、_animConfig 资产(按所创建的敌人类型命名)。"); - report.Add("★ AI(BrainGraph):先写一个 [AiDefinition(\"\")] 的 AiScript 子类," + - "再挂 EnemyAiBrain 组件并把 _definitionId 设为该 id。"); + report.Add("★ AI(BrainGraph):用菜单 BaseGames/AI/Enemy AI Recipe Wizard 建一个配方资产," + + "在 Inspector 选两层模块(未发现/交战),再挂 EnemyAiBrain 组件并把 _recipe 指向该资产。" + + "有独门机制的敌人才写 [AiDefinition] 的 AiScript 子类并改用 _definitionId。"); Undo.CollapseUndoOperations(undoGroup); Selection.activeGameObject = go; @@ -402,8 +403,9 @@ namespace BaseGames.Editor SetupPerceptionSystemSlots(sensorHub, new[] { "aggro", "attack_melee", "attack_range", "los" }, report); report.Add("填写 _bossId。"); report.Add("★ 挂载 BossSkillExecutor 并指定 BossSkillSO 列表(技能执行层)。"); - report.Add("★ AI(BrainGraph):先写一个 [AiDefinition(\"\")] 的 AiScript 子类," + - "再挂 EnemyAiBrain 组件并把 _definitionId 设为该 id。"); + report.Add("★ AI(BrainGraph):用菜单 BaseGames/AI/Enemy AI Recipe Wizard 建一个配方资产," + + "在 Inspector 选两层模块(未发现/交战),再挂 EnemyAiBrain 组件并把 _recipe 指向该资产。" + + "有独门机制的敌人才写 [AiDefinition] 的 AiScript 子类并改用 _definitionId。"); report.Add("多阶段 Boss 可在此 GameObject 上继续 AddComponent 阶段切换控制器。"); Selection.activeGameObject = go; @@ -495,10 +497,21 @@ namespace BaseGames.Editor GetOrAddComponent(go); - // BrainGraph AI:挂载决策组件并绑定定义 id(取代旧的 Opsive BehaviorTree) + // BrainGraph AI:挂载决策组件并绑定 AI 配方资产(取代旧的 Opsive BehaviorTree) var brain = GetOrAddComponent(go); - AssignString(brain, "_definitionId", "E001", report); - report.Add("✔ 已挂载 EnemyAiBrain 并绑定 AI 定义 id=E001(BrainGraph)。"); + var recipe = AssetDatabase.LoadAssetAtPath( + "Assets/_Game/Data/Enemies/E001/ENM_E001_Ai.asset"); + if (recipe == null) + { + // 根因暴露:配方缺失就报出来,不退回旧的字符串 id 路径掩盖。 + report.Add("✘ 未找到 AI 配方 ENM_E001_Ai —— 请先用菜单 BaseGames/AI/Enemy AI Recipe Wizard 创建。"); + } + else + { + AssignReference(brain, "_recipe", recipe, report); + AssignString(brain, "_definitionId", "", report); + report.Add("✔ 已挂载 EnemyAiBrain 并绑定 AI 配方 ENM_E001_Ai(BrainGraph)。"); + } Undo.CollapseUndoOperations(undoGroup); Selection.activeGameObject = go; @@ -598,8 +611,9 @@ namespace BaseGames.Editor report.Add("★ 将此对象放置于天花板,调整位置使 CapsuleCollider 正好贴合天花板底面。"); report.Add("★ HurtBox.enabled 初始为 false;钻出后由 CeilingHangStrikeAbility 在悬挂窗口开启。"); report.Add("★ attack_range 槽位为正下方 BoxCast(玩家经过检测区);按需在 Inspector 调整 offset/size。"); - report.Add("★ AI(BrainGraph):E002 尚无 AI 定义——先写 [AiDefinition(\"E002\")] 的 AiScript 子类," + - "再挂 EnemyAiBrain 并设 _definitionId=E002。"); + report.Add("★ AI(BrainGraph):用菜单 BaseGames/AI/Enemy AI Recipe Wizard 建一个配方资产," + + "在 Inspector 选两层模块(未发现/交战),再挂 EnemyAiBrain 组件并把 _recipe 指向该资产。" + + "有独门机制的敌人才写 [AiDefinition] 的 AiScript 子类并改用 _definitionId。"); report.Add("★ BD 树逻辑建议:Idle(悬挂)→ IsSensorDetecting(aggro) → UseAbility(CeilingDrop) → IsGrounded → Patrol(Pace)。"); Undo.CollapseUndoOperations(undoGroup); @@ -685,8 +699,9 @@ namespace BaseGames.Editor SetupPerceptionSystemSlots(sensorHub, new[] { "aggro", "los" }, report); report.Add("★ 将此对象放置于天花板下方;EnemyAbilityTrigger 在出生时(executeOnSpawn)自动、或被场景触发器调用 Trigger() 时执行下坠能力(e003_fall)。"); - report.Add("★ AI(BrainGraph):该敌人尚无 AI 定义——先写 [AiDefinition(\"\")] 的 AiScript 子类," + - "再挂 EnemyAiBrain 并把 _definitionId 设为该 id。"); + report.Add("★ AI(BrainGraph):用菜单 BaseGames/AI/Enemy AI Recipe Wizard 建一个配方资产," + + "在 Inspector 选两层模块(未发现/交战),再挂 EnemyAiBrain 组件并把 _recipe 指向该资产。" + + "有独门机制的敌人才写 [AiDefinition] 的 AiScript 子类并改用 _definitionId。"); Undo.CollapseUndoOperations(undoGroup); Selection.activeGameObject = go; @@ -815,8 +830,9 @@ namespace BaseGames.Editor SetupPerceptionSystemSlots(sensorHub, new[] { "aggro", "attack_melee", "attack_range", "sight" }, report); report.Add("★ AppearAbility._appearClip / FacePlayerAbility._faceClip 等动画 Clip 待美术接入后在 Inspector 指定。"); report.Add("★ 在 EnemyDeathSequence._deathPreClip 配置死亡前摇动画(两阶段死亡 Death_Pre 无敌)。"); - report.Add("★ AI(BrainGraph):该敌人尚无 AI 定义——先写 [AiDefinition(\"\")] 的 AiScript 子类," + - "再挂 EnemyAiBrain 并把 _definitionId 设为该 id。"); + report.Add("★ AI(BrainGraph):用菜单 BaseGames/AI/Enemy AI Recipe Wizard 建一个配方资产," + + "在 Inspector 选两层模块(未发现/交战),再挂 EnemyAiBrain 组件并把 _recipe 指向该资产。" + + "有独门机制的敌人才写 [AiDefinition] 的 AiScript 子类并改用 _definitionId。"); Undo.CollapseUndoOperations(undoGroup); Selection.activeGameObject = go; @@ -925,8 +941,9 @@ namespace BaseGames.Editor SetupPerceptionSystemSlots(sensorHub, new[] { "aggro", "attack_melee", "attack_range", "los" }, report); report.Add("★ 在 EnemyDeathSequence._deathPreClip 上添加 AnimationEvent 调用 SpawnProjectile(\"spawn_e003\"),由 EnemySpawnerOnEvent 从对象池生成幼蛭(ENM_YouZhi)。"); - report.Add("★ AI(BrainGraph):该敌人尚无 AI 定义——先写 [AiDefinition(\"\")] 的 AiScript 子类," + - "再挂 EnemyAiBrain 并把 _definitionId 设为该 id。"); + report.Add("★ AI(BrainGraph):用菜单 BaseGames/AI/Enemy AI Recipe Wizard 建一个配方资产," + + "在 Inspector 选两层模块(未发现/交战),再挂 EnemyAiBrain 组件并把 _recipe 指向该资产。" + + "有独门机制的敌人才写 [AiDefinition] 的 AiScript 子类并改用 _definitionId。"); Undo.CollapseUndoOperations(undoGroup); Selection.activeGameObject = go; @@ -1024,8 +1041,9 @@ namespace BaseGames.Editor } SetupPerceptionSystemSlots(sensorHub, new[] { "aggro", "los" }, report); - report.Add("★ AI(BrainGraph):E006 尚无 AI 定义——先写 [AiDefinition(\"E006\")] 的 AiScript 子类," + - "再挂 EnemyAiBrain 并设 _definitionId=E006。"); + report.Add("★ AI(BrainGraph):用菜单 BaseGames/AI/Enemy AI Recipe Wizard 建一个配方资产," + + "在 Inspector 选两层模块(未发现/交战),再挂 EnemyAiBrain 组件并把 _recipe 指向该资产。" + + "有独门机制的敌人才写 [AiDefinition] 的 AiScript 子类并改用 _definitionId。"); Undo.CollapseUndoOperations(undoGroup); Selection.activeGameObject = go; @@ -1168,8 +1186,9 @@ namespace BaseGames.Editor report.Add("★ FanCombo 三段 HitBox 与 Tornado HitBox 已挂入 BossSkillExecutor._hitBoxes。"); report.Add("★ 将 BoomerangMuzzle / TornadoMuzzle / WindStoneMuzzle 拖入对应 BossSkillSO 的发射点字段(如有)。"); report.Add("★ 回旋扇收招/阶段过渡/击败演出等动画 Clip 待美术接入后在 ChaoFengBoss Inspector 指定。"); - report.Add("★ AI(BrainGraph):嘲风尚无 AI 定义——先写 [AiDefinition(\"ChaoFeng\")] 的 AiScript 子类," + - "再挂 EnemyAiBrain 并设 _definitionId=ChaoFeng(技能执行仍由 BossSkillExecutor 负责)。"); + report.Add("★ AI(BrainGraph):用菜单 BaseGames/AI/Enemy AI Recipe Wizard 建一个配方资产," + + "在 Inspector 选两层模块(未发现/交战),再挂 EnemyAiBrain 组件并把 _recipe 指向该资产" + + "(技能执行仍由 BossSkillExecutor 负责)。有独门机制的敌人才写 [AiDefinition] 的 AiScript 子类并改用 _definitionId。"); Undo.CollapseUndoOperations(undoGroup); Selection.activeGameObject = go; diff --git a/Assets/_Game/Scripts/Enemies/AIBrain/Ai/E001CaoZhiAi.cs b/Assets/_Game/Scripts/Enemies/AIBrain/Ai/E001CaoZhiAi.cs deleted file mode 100644 index e5cc6c24..00000000 --- a/Assets/_Game/Scripts/Enemies/AIBrain/Ai/E001CaoZhiAi.cs +++ /dev/null @@ -1,19 +0,0 @@ -using BaseGames.AI; - -namespace BaseGames.Enemies -{ - /// - /// E001(草蛭)AI —— 纯决策层,组装两层模块。 - /// 出生伪装静止(伪装成石头),一旦交战过就只回巡逻;追击=带冷却的接触冲锋, - /// 起手即锁定、打完回巡逻走冷却;死亡演出走物理状态机(EnemyBase.PerformDeath)。 - /// AI 只决策;移动 / 朝向 / 速度 / 动画 / 伤害全部在能力与 EnemyLocomotion 里实现。 - /// 依据 Docs/Game/敌人/小怪/E001_草蛭.md。 - /// - [AiDefinition("E001")] - public sealed class E001CaoZhiAi : AiScript - { - protected override void Build(BrainBuilder b) => PerceptionSkeleton.Add(b, - unaware: new DisguiseThenPatrol(), - engagement: new RushEngagement("e001_chase", RushExit.Committed)); - } -} diff --git a/Assets/_Game/Scripts/Enemies/AIBrain/Ai/E001CaoZhiAi.cs.meta b/Assets/_Game/Scripts/Enemies/AIBrain/Ai/E001CaoZhiAi.cs.meta deleted file mode 100644 index 99a8f7d5..00000000 --- a/Assets/_Game/Scripts/Enemies/AIBrain/Ai/E001CaoZhiAi.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 82a595c9b77505c448845d8cd1a56064 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: