feat(enemy): 嘲风迁移到新轨——能力资产 + 对象树 + 开战触发

删 5 个空 BossSkillSO,用向导重建 6 个 EnemyAbilitySO(含入场演出)。
预制体经放置工具重新产出:EnemyAiBrain(_definitionId=ChaoFeng) +
BossPhaseAbilityGate + 6 个能力组件,不再有 BossSkillExecutor。
TestRoomA 加开战触发区。三件自检 0 error,EditMode 260/260。

首次真正跑通两条脚手架,暴露并修掉三个它们的缺陷:

1. 放置工具漏挂 EnemyLocomotion(PlaceChaoFeng 及其余 7 个敌人放置入口)。
   EnemyBase.Awake 找不到它即报错且 Locomotion 为 null,
   AiStateFragments.ApplyLocomotion 直接 NRE、AiRuntime 构造失败——
   Boss 建不出决策层,完全不动。已在所有敌人放置入口补齐。
2. 向导把空中阶段的 wind_stone 建成 requiresGrounded=true(SO 默认值)。
   Boss 浮空后 IsGrounded 恒 false,选招器把它滤掉,空中阶段站着不打。
   能力定义表加 grounded 列,阶段 1 的招显式置 false。
3. BossPhaseAbilityGate.ApplyPhase 只在 EnterPhase 与 OnSpawn 调用,
   直接摆场景里的 Boss 两条路径都不走,开局后续阶段的招仍在候选池里。
   BossBase.Start 补一次初始阶段应用。

另:Phase1_Tornado_HitBox 确认零消费者(龙卷判定随弹体走),
从放置工具删除其创建与伤害源绑定;
EnemyBrainContext.UseAbility 对解析不到的能力 id 改为 LogError,
不再静默返回 false(CLAUDE.md 第 6 条);
新增 PlaceBossFightTrigger 脚手架(此前无对应创建入口,属裸建)。

播放模式实测状态序列(TestRoomA,玩家走进触发区):
Wait →(Engaged) Intro → Ground⇄GroundAttack →(hp<50%) PhaseTransition
→ Air⇄AirAttack,浮空生效,阶段门按阶段换池,全程 0 报错。
动画 Clip 未接入,PlayClipAbility 空 clip 立即完成,故只验证了状态流转,
判定时序待美术接入后再校。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-30 16:02:14 +08:00
co-authored by Claude Opus 5
parent bdeefca75b
commit 877d2f5fef
13 changed files with 844 additions and 273 deletions
@@ -9,32 +9,29 @@ MonoBehaviour:
m_GameObject: {fileID: 0} m_GameObject: {fileID: 0}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: de92221c7c3fb4a42a7cd122a8f97632, type: 3} m_Script: {fileID: 11500000, guid: fc81345eb5294d643b4242eac215c5fc, type: 3}
m_Name: ABL_ChaoFeng_Boomerang m_Name: ABL_ChaoFeng_Boomerang
m_EditorClassIdentifier: m_EditorClassIdentifier:
skillId: boomerang abilityId: boomerang
displayName: Boomerang designNote: "\u9636\u6BB5 0 \u62DB\u5F0F\uFF1B\u9636\u6BB5\u53EF\u7528\u6027\u7531
designNote: BossPhaseAbilityGate \u914D\u7F6E"
category: 0 attackSequence: []
skillType: 0 cooldown: 4
availablePhaseIndices: 00000000 telegraphVfxKey:
attackPatterns: [] telegraphDuration: 0
vulnerabilityWindows: [] interruptOnHurt: 1
interactionTags: 0 interruptOnStagger: 1
sequenceOnHit: {fileID: 0} preferredMinRange: 0
sequenceOnMiss: {fileID: 0} preferredMaxRange: 5
counterResponses: [] requiresLineOfSight: 1
arenaEvents: [] requiresGrounded: 1
resourceCost: exclusionGroup:
resourceId: priority: 0
cost: 0 category: 1
minRequired: 0 weight: 1
buildsRage: 0 rangeRadius: 9
poiseWindow: rangeOffset: {x: 0, y: 0}
Level: 0 clip:
NormalizedStart: 0
NormalizedEnd: 0
skillAnimation:
_FadeDuration: 0.25 _FadeDuration: 0.25
_Speed: 1 _Speed: 1
_Events: _Events:
@@ -43,8 +40,6 @@ MonoBehaviour:
_Names: [] _Names: []
_Clip: {fileID: 0} _Clip: {fileID: 0}
_NormalizedStartTime: NaN _NormalizedStartTime: NaN
cooldown: 0
weight: 1
references: references:
version: 2 version: 2
RefIds: [] RefIds: []
@@ -9,42 +9,25 @@ MonoBehaviour:
m_GameObject: {fileID: 0} m_GameObject: {fileID: 0}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: de92221c7c3fb4a42a7cd122a8f97632, type: 3} m_Script: {fileID: 11500000, guid: 9050afa76362dff469c64fbb48c9ff8d, type: 3}
m_Name: ABL_ChaoFeng_FanCombo m_Name: ABL_ChaoFeng_FanCombo
m_EditorClassIdentifier: m_EditorClassIdentifier:
skillId: fan_combo abilityId: fan_combo
displayName: FanCombo designNote: "\u9636\u6BB5 0 \u62DB\u5F0F\uFF1B\u9636\u6BB5\u53EF\u7528\u6027\u7531
designNote: BossPhaseAbilityGate \u914D\u7F6E"
category: 0 attackSequence: []
skillType: 0 cooldown: 2.5
availablePhaseIndices: 00000000 telegraphVfxKey:
attackPatterns: [] telegraphDuration: 0
vulnerabilityWindows: [] interruptOnHurt: 1
interactionTags: 0 interruptOnStagger: 1
sequenceOnHit: {fileID: 0} preferredMinRange: 0
sequenceOnMiss: {fileID: 0} preferredMaxRange: 5
counterResponses: [] requiresLineOfSight: 1
arenaEvents: [] requiresGrounded: 1
resourceCost: exclusionGroup:
resourceId: priority: 0
cost: 0 category: 1
minRequired: 0
buildsRage: 0
poiseWindow:
Level: 0
NormalizedStart: 0
NormalizedEnd: 0
skillAnimation:
_FadeDuration: 0.25
_Speed: 1
_Events:
_NormalizedTimes: []
_Callbacks: []
_Names: []
_Clip: {fileID: 0}
_NormalizedStartTime: NaN
cooldown: 0
weight: 1.5 weight: 1.5
references: rangeRadius: 2.5
version: 2 rangeOffset: {x: 0, y: 0}
RefIds: []
@@ -0,0 +1,44 @@
%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: fc81345eb5294d643b4242eac215c5fc, type: 3}
m_Name: ABL_ChaoFeng_Intro
m_EditorClassIdentifier:
abilityId: chaofeng_intro
designNote: "\u5165\u573A\u6F14\u51FA\uFF0C\u4E0D\u8FDB\u9009\u62DB\u6C60"
attackSequence: []
cooldown: 0
telegraphVfxKey:
telegraphDuration: 0
interruptOnHurt: 1
interruptOnStagger: 1
preferredMinRange: 0
preferredMaxRange: 5
requiresLineOfSight: 1
requiresGrounded: 1
exclusionGroup:
priority: 0
category: 0
weight: 0
rangeRadius: 0
rangeOffset: {x: 0, y: 0}
clip:
_FadeDuration: 0.25
_Speed: 1
_Events:
_NormalizedTimes: []
_Callbacks: []
_Names: []
_Clip: {fileID: 0}
_NormalizedStartTime: NaN
references:
version: 2
RefIds: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eddeb2d9e64934d4eab9acf5efd8902e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:
@@ -9,32 +9,29 @@ MonoBehaviour:
m_GameObject: {fileID: 0} m_GameObject: {fileID: 0}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: de92221c7c3fb4a42a7cd122a8f97632, type: 3} m_Script: {fileID: 11500000, guid: fc81345eb5294d643b4242eac215c5fc, type: 3}
m_Name: ABL_ChaoFeng_TornadoLarge m_Name: ABL_ChaoFeng_TornadoLarge
m_EditorClassIdentifier: m_EditorClassIdentifier:
skillId: tornado_large abilityId: tornado_large
displayName: TornadoLarge designNote: "\u9636\u6BB5 0 \u62DB\u5F0F\uFF1B\u9636\u6BB5\u53EF\u7528\u6027\u7531
designNote: BossPhaseAbilityGate \u914D\u7F6E"
category: 0 attackSequence: []
skillType: 0 cooldown: 6
availablePhaseIndices: 00000000 telegraphVfxKey:
attackPatterns: [] telegraphDuration: 0
vulnerabilityWindows: [] interruptOnHurt: 1
interactionTags: 0 interruptOnStagger: 1
sequenceOnHit: {fileID: 0} preferredMinRange: 0
sequenceOnMiss: {fileID: 0} preferredMaxRange: 5
counterResponses: [] requiresLineOfSight: 1
arenaEvents: [] requiresGrounded: 1
resourceCost: exclusionGroup:
resourceId: priority: 0
cost: 0 category: 1
minRequired: 0 weight: 0.8
buildsRage: 0 rangeRadius: 12
poiseWindow: rangeOffset: {x: 0, y: 0}
Level: 0 clip:
NormalizedStart: 0
NormalizedEnd: 0
skillAnimation:
_FadeDuration: 0.25 _FadeDuration: 0.25
_Speed: 1 _Speed: 1
_Events: _Events:
@@ -43,8 +40,6 @@ MonoBehaviour:
_Names: [] _Names: []
_Clip: {fileID: 0} _Clip: {fileID: 0}
_NormalizedStartTime: NaN _NormalizedStartTime: NaN
cooldown: 0
weight: 0.8
references: references:
version: 2 version: 2
RefIds: [] RefIds: []
@@ -9,32 +9,29 @@ MonoBehaviour:
m_GameObject: {fileID: 0} m_GameObject: {fileID: 0}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: de92221c7c3fb4a42a7cd122a8f97632, type: 3} m_Script: {fileID: 11500000, guid: fc81345eb5294d643b4242eac215c5fc, type: 3}
m_Name: ABL_ChaoFeng_TornadoSmall m_Name: ABL_ChaoFeng_TornadoSmall
m_EditorClassIdentifier: m_EditorClassIdentifier:
skillId: tornado_small abilityId: tornado_small
displayName: TornadoSmall designNote: "\u9636\u6BB5 0 \u62DB\u5F0F\uFF1B\u9636\u6BB5\u53EF\u7528\u6027\u7531
designNote: BossPhaseAbilityGate \u914D\u7F6E"
category: 0 attackSequence: []
skillType: 0 cooldown: 3.5
availablePhaseIndices: 00000000 telegraphVfxKey:
attackPatterns: [] telegraphDuration: 0
vulnerabilityWindows: [] interruptOnHurt: 1
interactionTags: 0 interruptOnStagger: 1
sequenceOnHit: {fileID: 0} preferredMinRange: 0
sequenceOnMiss: {fileID: 0} preferredMaxRange: 5
counterResponses: [] requiresLineOfSight: 1
arenaEvents: [] requiresGrounded: 1
resourceCost: exclusionGroup:
resourceId: priority: 0
cost: 0 category: 1
minRequired: 0 weight: 1.2
buildsRage: 0 rangeRadius: 8
poiseWindow: rangeOffset: {x: 0, y: 0}
Level: 0 clip:
NormalizedStart: 0
NormalizedEnd: 0
skillAnimation:
_FadeDuration: 0.25 _FadeDuration: 0.25
_Speed: 1 _Speed: 1
_Events: _Events:
@@ -43,8 +40,6 @@ MonoBehaviour:
_Names: [] _Names: []
_Clip: {fileID: 0} _Clip: {fileID: 0}
_NormalizedStartTime: NaN _NormalizedStartTime: NaN
cooldown: 0
weight: 1.2
references: references:
version: 2 version: 2
RefIds: [] RefIds: []
@@ -9,32 +9,29 @@ MonoBehaviour:
m_GameObject: {fileID: 0} m_GameObject: {fileID: 0}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: de92221c7c3fb4a42a7cd122a8f97632, type: 3} m_Script: {fileID: 11500000, guid: fc81345eb5294d643b4242eac215c5fc, type: 3}
m_Name: ABL_ChaoFeng_WindStone m_Name: ABL_ChaoFeng_WindStone
m_EditorClassIdentifier: m_EditorClassIdentifier:
skillId: wind_stone abilityId: wind_stone
displayName: WindStone designNote: "\u9636\u6BB5 1 \u62DB\u5F0F\uFF1B\u9636\u6BB5\u53EF\u7528\u6027\u7531
designNote: BossPhaseAbilityGate \u914D\u7F6E"
category: 0 attackSequence: []
skillType: 0 cooldown: 3
availablePhaseIndices: 01000000 telegraphVfxKey:
attackPatterns: [] telegraphDuration: 0
vulnerabilityWindows: [] interruptOnHurt: 1
interactionTags: 0 interruptOnStagger: 1
sequenceOnHit: {fileID: 0} preferredMinRange: 0
sequenceOnMiss: {fileID: 0} preferredMaxRange: 5
counterResponses: [] requiresLineOfSight: 1
arenaEvents: [] requiresGrounded: 0
resourceCost: exclusionGroup:
resourceId: priority: 0
cost: 0 category: 1
minRequired: 0 weight: 1
buildsRage: 0 rangeRadius: 12
poiseWindow: rangeOffset: {x: 0, y: 0}
Level: 0 clip:
NormalizedStart: 0
NormalizedEnd: 0
skillAnimation:
_FadeDuration: 0.25 _FadeDuration: 0.25
_Speed: 1 _Speed: 1
_Events: _Events:
@@ -43,8 +40,6 @@ MonoBehaviour:
_Names: [] _Names: []
_Clip: {fileID: 0} _Clip: {fileID: 0}
_NormalizedStartTime: NaN _NormalizedStartTime: NaN
cooldown: 0
weight: 1
references: references:
version: 2 version: 2
RefIds: [] RefIds: []
@@ -1,5 +1,58 @@
%YAML 1.1 %YAML 1.1
%TAG !u! tag:unity3d.com,2011: %TAG !u! tag:unity3d.com,2011:
--- !u!1 &979165801027136474
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5181544129696273283}
- component: {fileID: 7940098084422673156}
m_Layer: 0
m_Name: MeleeAttackAbility_FanCombo
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5181544129696273283
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 979165801027136474}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5296480593323786894}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &7940098084422673156
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 979165801027136474}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 971ba82e05d87234e8b944760542e47c, type: 3}
m_Name:
m_EditorClassIdentifier:
_config: {fileID: 11400000, guid: b13d174edfd74654188f1cd08f072123, type: 2}
_hitBoxSlots:
- slotName: fan_1
hitBox: {fileID: 230484937522067432}
- slotName: fan_2
hitBox: {fileID: 9170136654108653383}
- slotName: fan_3
hitBox: {fileID: 4630646362173111049}
_faceTargetOnStart: 1
--- !u!1 &1231266844344956596 --- !u!1 &1231266844344956596
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -62,6 +115,51 @@ Transform:
m_Children: [] m_Children: []
m_Father: {fileID: 2025611111464161772} m_Father: {fileID: 2025611111464161772}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1825922247716397416
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8959989091743334252}
- component: {fileID: 8219329344573822582}
m_Layer: 0
m_Name: PlayClipAbility_Intro
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8959989091743334252
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1825922247716397416}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5296480593323786894}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8219329344573822582
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1825922247716397416}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a26fca0fa72894a4da1a5a58ee023154, type: 3}
m_Name:
m_EditorClassIdentifier:
_config: {fileID: 11400000, guid: eddeb2d9e64934d4eab9acf5efd8902e, type: 2}
--- !u!1 &2290525692157171072 --- !u!1 &2290525692157171072
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -191,7 +289,7 @@ Transform:
m_GameObject: {fileID: 2904988631977355437} m_GameObject: {fileID: 2904988631977355437}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalPosition: {x: 0, y: 1, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
@@ -285,7 +383,7 @@ SpriteRenderer:
m_WasSpriteAssigned: 1 m_WasSpriteAssigned: 1
m_MaskInteraction: 0 m_MaskInteraction: 0
m_SpriteSortPoint: 0 m_SpriteSortPoint: 0
--- !u!1 &3015807690815610513 --- !u!1 &2916559493138038639
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
@@ -293,99 +391,88 @@ GameObject:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
serializedVersion: 6 serializedVersion: 6
m_Component: m_Component:
- component: {fileID: 1409576167468823365} - component: {fileID: 7149986575129040968}
- component: {fileID: 2458103135947848963} - component: {fileID: 209352783170023499}
- component: {fileID: 2450883169310398879} m_Layer: 0
m_Layer: 25 m_Name: PlayClipAbility_Boomerang
m_Name: Phase1_Tornado_HitBox
m_TagString: Untagged m_TagString: Untagged
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 0 m_IsActive: 1
--- !u!4 &1409576167468823365 --- !u!4 &7149986575129040968
Transform: Transform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3015807690815610513} m_GameObject: {fileID: 2916559493138038639}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
m_Father: {fileID: 2025611111464161772} m_Father: {fileID: 5296480593323786894}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!61 &2458103135947848963 --- !u!114 &209352783170023499
BoxCollider2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3015807690815610513}
m_Enabled: 1
m_Density: 1
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_ForceSendLayers:
serializedVersion: 2
m_Bits: 4294967295
m_ForceReceiveLayers:
serializedVersion: 2
m_Bits: 4294967295
m_ContactCaptureLayers:
serializedVersion: 2
m_Bits: 4294967295
m_CallbackLayers:
serializedVersion: 2
m_Bits: 4294967295
m_IsTrigger: 1
m_UsedByEffector: 0
m_UsedByComposite: 0
m_Offset: {x: 0, y: 0}
m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0, y: 0}
oldSize: {x: 0, y: 0}
newSize: {x: 0, y: 0}
adaptiveTilingThreshold: 0
drawMode: 0
adaptiveTiling: 0
m_AutoTiling: 0
serializedVersion: 2
m_Size: {x: 0.6, y: 1.2}
m_EdgeRadius: 0
--- !u!114 &2450883169310398879
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3015807690815610513} m_GameObject: {fileID: 2916559493138038639}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a655e2461396a8348a32a13144438e8e, type: 3} m_Script: {fileID: 11500000, guid: a26fca0fa72894a4da1a5a58ee023154, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
_defaultSource: {fileID: 11400000, guid: caae9c7600281fe4e8d8637fa3fd2ca1, type: 2} _config: {fileID: 11400000, guid: 6076c1b736f69af4c9048d9d4e7ec768, type: 2}
_hitCooldown: 0.1 --- !u!1 &3224375973558534567
_hitMode: 0 GameObject:
_hitInterval: 0.5 m_ObjectHideFlags: 0
_targetLayers: m_CorrespondingSourceObject: {fileID: 0}
serializedVersion: 2 m_PrefabInstance: {fileID: 0}
m_Bits: 4294967295 m_PrefabAsset: {fileID: 0}
_id: serializedVersion: 6
_rivalHitBoxMask: m_Component:
serializedVersion: 2 - component: {fileID: 6052463430739264899}
m_Bits: 0 - component: {fileID: 1436318798284677237}
m_Layer: 0
m_Name: PlayClipAbility_TornadoLarge
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &6052463430739264899
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3224375973558534567}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5296480593323786894}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1436318798284677237
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3224375973558534567}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a26fca0fa72894a4da1a5a58ee023154, type: 3}
m_Name:
m_EditorClassIdentifier:
_config: {fileID: 11400000, guid: 27037bf4ed7188741ba55bb82fdd8fa9, type: 2}
--- !u!1 &3277627412355666927 --- !u!1 &3277627412355666927
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -487,6 +574,43 @@ MonoBehaviour:
_rivalHitBoxMask: _rivalHitBoxMask:
serializedVersion: 2 serializedVersion: 2
m_Bits: 0 m_Bits: 0
--- !u!1 &3801371647583863605
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5296480593323786894}
m_Layer: 0
m_Name: Abilities
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5296480593323786894
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3801371647583863605}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8959989091743334252}
- {fileID: 5181544129696273283}
- {fileID: 7149986575129040968}
- {fileID: 3558980470815650670}
- {fileID: 6052463430739264899}
- {fileID: 4717475142090746934}
m_Father: {fileID: 2025611111464161772}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &4177669747969163254 --- !u!1 &4177669747969163254
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -634,7 +758,10 @@ GameObject:
- component: {fileID: 973594085864951384} - component: {fileID: 973594085864951384}
- component: {fileID: 5341485012012430190} - component: {fileID: 5341485012012430190}
- component: {fileID: 8088437629491012474} - component: {fileID: 8088437629491012474}
- component: {fileID: 3437191888218430966} - component: {fileID: 3133205082234065514}
- component: {fileID: 3942835667027582048}
- component: {fileID: 4739322141714049461}
- component: {fileID: 5585087268776340831}
- component: {fileID: 1810872916174435854} - component: {fileID: 1810872916174435854}
- component: {fileID: 1201243240150589714} - component: {fileID: 1201243240150589714}
- component: {fileID: 6858366591425580670} - component: {fileID: 6858366591425580670}
@@ -654,20 +781,20 @@ Transform:
m_GameObject: {fileID: 7781161515165213226} m_GameObject: {fileID: 7781161515165213226}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 1968.4287, y: 77.1997, z: 0} m_LocalPosition: {x: 98, y: 21, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: m_Children:
- {fileID: 5517492589801030229} - {fileID: 5517492589801030229}
- {fileID: 6397871098464242200} - {fileID: 6397871098464242200}
- {fileID: 80973138644072513}
- {fileID: 376149298811787739} - {fileID: 376149298811787739}
- {fileID: 8176707102135037433} - {fileID: 8176707102135037433}
- {fileID: 8814706017035826473} - {fileID: 8814706017035826473}
- {fileID: 1409576167468823365}
- {fileID: 7580995191264333933} - {fileID: 7580995191264333933}
- {fileID: 2397879757105861778} - {fileID: 2397879757105861778}
- {fileID: 4107279870065028942} - {fileID: 4107279870065028942}
- {fileID: 80973138644072513} - {fileID: 5296480593323786894}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!50 &6158877404411547497 --- !u!50 &6158877404411547497
@@ -729,7 +856,7 @@ BoxCollider2D:
m_IsTrigger: 0 m_IsTrigger: 0
m_UsedByEffector: 0 m_UsedByEffector: 0
m_UsedByComposite: 0 m_UsedByComposite: 0
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 1}
m_SpriteTilingProperty: m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0} border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0, y: 0} pivot: {x: 0, y: 0}
@@ -763,7 +890,7 @@ MonoBehaviour:
_animancer: {fileID: 8300109994792221770} _animancer: {fileID: 8300109994792221770}
_feedback: {fileID: 5341485012012430190} _feedback: {fileID: 5341485012012430190}
_hurtBox: {fileID: 6579043664862402528} _hurtBox: {fileID: 6579043664862402528}
_bodyCollider: {fileID: 0} _bodyCollider: {fileID: 4474032822853512122}
_patrolZone: {fileID: 0} _patrolZone: {fileID: 0}
_onEnemyDied: {fileID: 11400000, guid: def849e2c5ec8204eae6b083b02307aa, type: 2} _onEnemyDied: {fileID: 11400000, guid: def849e2c5ec8204eae6b083b02307aa, type: 2}
_onPlayerSpawned: {fileID: 11400000, guid: 7e2c7e614f6627b449a244ab44443adf, type: 2} _onPlayerSpawned: {fileID: 11400000, guid: 7e2c7e614f6627b449a244ab44443adf, type: 2}
@@ -775,6 +902,8 @@ MonoBehaviour:
_onBossPhaseChanged: {fileID: 11400000, guid: 9f49e575a92a7fb43af755ba1840abd2, type: 2} _onBossPhaseChanged: {fileID: 11400000, guid: 9f49e575a92a7fb43af755ba1840abd2, type: 2}
_skillExecutor: {fileID: 0} _skillExecutor: {fileID: 0}
_bossResource: {fileID: 0} _bossResource: {fileID: 0}
_phaseGate: {fileID: 5585087268776340831}
_arenaAnchors: {fileID: 0}
_onParrySuccess: {fileID: 0} _onParrySuccess: {fileID: 0}
_floatController: {fileID: 1810872916174435854} _floatController: {fileID: 1810872916174435854}
_knockdownCounter: {fileID: 1201243240150589714} _knockdownCounter: {fileID: 1201243240150589714}
@@ -908,14 +1037,13 @@ MonoBehaviour:
_dbg_IsWallAhead: 0 _dbg_IsWallAhead: 0
_dbg_IsLedgeAhead: 0 _dbg_IsLedgeAhead: 0
_dbg_IsTurning: 0 _dbg_IsTurning: 0
_dbg_NavDriving: 0
_dbg_Input_MoveDir: 0 _dbg_Input_MoveDir: 0
_dbg_Input_MoveSpeed: 0 _dbg_Input_MoveSpeed: 0
_dbg_Input_WantStop: 0 _dbg_Input_WantStop: 0
_dbg_Input_WantFace: 0 _dbg_Input_WantFace: 0
_dbg_Input_FaceTargetPos: {x: 0, y: 0} _dbg_Input_FaceTargetPos: {x: 0, y: 0}
_dbg_Input_FaceDir: 0 _dbg_Input_FaceDir: 0
--- !u!114 &3437191888218430966 --- !u!114 &3133205082234065514
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
@@ -924,27 +1052,69 @@ MonoBehaviour:
m_GameObject: {fileID: 7781161515165213226} m_GameObject: {fileID: 7781161515165213226}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4dfa1c525eaca5640b3cfe945626a466, type: 3} m_Script: {fileID: 11500000, guid: 8caa8e247c70b7445820efe80d2da0ec, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
_hitBoxes: _stoppingDistance: 0.2
- {fileID: 230484937522067432} _wanderMinRange: 1.5
- {fileID: 9170136654108653383} _wanderMaxRange: 5
- {fileID: 4630646362173111049} _stallWindowSeconds: 0.4
- {fileID: 2450883169310398879} _stallMinProgress: 0.05
_weakPointSystem: {fileID: 0} --- !u!114 &3942835667027582048
_animancer: {fileID: 8300109994792221770} MonoBehaviour:
_bossId: ChaoFeng m_ObjectHideFlags: 0
_onBossSkillStarted: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
_onBossSkillEnded: {fileID: 0} m_PrefabInstance: {fileID: 0}
_playerTransform: {fileID: 0} m_PrefabAsset: {fileID: 0}
_skills: m_GameObject: {fileID: 7781161515165213226}
- {fileID: 11400000, guid: 6076c1b736f69af4c9048d9d4e7ec768, type: 2} m_Enabled: 1
- {fileID: 11400000, guid: b13d174edfd74654188f1cd08f072123, type: 2} m_EditorHideFlags: 0
- {fileID: 11400000, guid: 7cb2926dd5b97e64b9e37f07124ae307, type: 2} m_Script: {fileID: 11500000, guid: 9201463979893884288d3645a607eb90, type: 3}
- {fileID: 11400000, guid: 27037bf4ed7188741ba55bb82fdd8fa9, type: 2} m_Name:
- {fileID: 11400000, guid: 02b79b9dc903c824786ed3cc3c3e225e, type: 2} m_EditorClassIdentifier:
_repeatRangeCheck: 8 _patrolStrategy: 0
_wanderPauseMin: 0.5
_wanderPauseMax: 1.5
_waypoints: []
_pingPong: 0
_waypointArriveRadius: 0.4
--- !u!114 &4739322141714049461
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7781161515165213226}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d92d657c6bbdfe246a7333e04f79f8f7, type: 3}
m_Name:
m_EditorClassIdentifier:
_recipe: {fileID: 0}
_definitionId: ChaoFeng
--- !u!114 &5585087268776340831
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7781161515165213226}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a9f265c84eb5db34b8fd06472949ee83, type: 3}
m_Name:
m_EditorClassIdentifier:
_entries:
- ability: {fileID: 7940098084422673156}
phases: 00000000
- ability: {fileID: 209352783170023499}
phases: 00000000
- ability: {fileID: 536854426800190861}
phases: 00000000
- ability: {fileID: 1436318798284677237}
phases: 00000000
- ability: {fileID: 9004908790283913037}
phases: 01000000
--- !u!114 &1810872916174435854 --- !u!114 &1810872916174435854
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1115,6 +1285,96 @@ MonoBehaviour:
obstructLayer: obstructLayer:
serializedVersion: 2 serializedVersion: 2
m_Bits: 0 m_Bits: 0
--- !u!1 &7806369876961327953
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3558980470815650670}
- component: {fileID: 536854426800190861}
m_Layer: 0
m_Name: PlayClipAbility_TornadoSmall
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3558980470815650670
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7806369876961327953}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5296480593323786894}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &536854426800190861
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7806369876961327953}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a26fca0fa72894a4da1a5a58ee023154, type: 3}
m_Name:
m_EditorClassIdentifier:
_config: {fileID: 11400000, guid: 7cb2926dd5b97e64b9e37f07124ae307, type: 2}
--- !u!1 &7888626137513785884
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4717475142090746934}
- component: {fileID: 9004908790283913037}
m_Layer: 0
m_Name: PlayClipAbility_WindStone
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4717475142090746934
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7888626137513785884}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5296480593323786894}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &9004908790283913037
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7888626137513785884}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a26fca0fa72894a4da1a5a58ee023154, type: 3}
m_Name:
m_EditorClassIdentifier:
_config: {fileID: 11400000, guid: 02b79b9dc903c824786ed3cc3c3e225e, type: 2}
--- !u!1 &8109938981782931710 --- !u!1 &8109938981782931710
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1124,7 +1384,7 @@ GameObject:
serializedVersion: 6 serializedVersion: 6
m_Component: m_Component:
- component: {fileID: 6397871098464242200} - component: {fileID: 6397871098464242200}
- component: {fileID: 5510659119725211148} - component: {fileID: 5509146531381767278}
- component: {fileID: 6579043664862402528} - component: {fileID: 6579043664862402528}
m_Layer: 27 m_Layer: 27
m_Name: HurtBox m_Name: HurtBox
@@ -1148,8 +1408,8 @@ Transform:
m_Children: [] m_Children: []
m_Father: {fileID: 2025611111464161772} m_Father: {fileID: 2025611111464161772}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!70 &5510659119725211148 --- !u!61 &5509146531381767278
CapsuleCollider2D: BoxCollider2D:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
@@ -1180,9 +1440,19 @@ CapsuleCollider2D:
m_IsTrigger: 1 m_IsTrigger: 1
m_UsedByEffector: 0 m_UsedByEffector: 0
m_UsedByComposite: 0 m_UsedByComposite: 0
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 1}
m_Size: {x: 1.1, y: 1.9} m_SpriteTilingProperty:
m_Direction: 0 border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0, y: 0}
oldSize: {x: 0, y: 0}
newSize: {x: 0, y: 0}
adaptiveTilingThreshold: 0
drawMode: 0
adaptiveTiling: 0
m_AutoTiling: 0
serializedVersion: 2
m_Size: {x: 1.2, y: 2}
m_EdgeRadius: 0
--- !u!114 &6579043664862402528 --- !u!114 &6579043664862402528
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -1195,7 +1465,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: d7b7a233d7f70aa4f86b473412b826de, type: 3} m_Script: {fileID: 11500000, guid: d7b7a233d7f70aa4f86b473412b826de, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
_onDamageDealt: {fileID: 0} _onDamageDealt: {fileID: 11400000, guid: eebd58cfef3527940949a8a7655a343b, type: 2}
_onHitConfirmed: {fileID: 11400000, guid: a67d56f5124e0db4f98f326c74be8091, type: 2} _onHitConfirmed: {fileID: 11400000, guid: a67d56f5124e0db4f98f326c74be8091, type: 2}
--- !u!1 &8920059952006723162 --- !u!1 &8920059952006723162
GameObject: GameObject:
@@ -1206,7 +1476,7 @@ GameObject:
serializedVersion: 6 serializedVersion: 6
m_Component: m_Component:
- component: {fileID: 80973138644072513} - component: {fileID: 80973138644072513}
- component: {fileID: 6125666153035542197} - component: {fileID: 4535625604443592544}
- component: {fileID: 4960688227238377219} - component: {fileID: 4960688227238377219}
- component: {fileID: 3072716489886911545} - component: {fileID: 3072716489886911545}
m_Layer: 25 m_Layer: 25
@@ -1231,8 +1501,8 @@ Transform:
m_Children: [] m_Children: []
m_Father: {fileID: 2025611111464161772} m_Father: {fileID: 2025611111464161772}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!70 &6125666153035542197 --- !u!61 &4535625604443592544
CapsuleCollider2D: BoxCollider2D:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
@@ -1263,9 +1533,19 @@ CapsuleCollider2D:
m_IsTrigger: 1 m_IsTrigger: 1
m_UsedByEffector: 0 m_UsedByEffector: 0
m_UsedByComposite: 0 m_UsedByComposite: 0
m_Offset: {x: 0, y: 0} m_Offset: {x: 0, y: 1}
m_Size: {x: 1.1, y: 1.9} m_SpriteTilingProperty:
m_Direction: 0 border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0, y: 0}
oldSize: {x: 0, y: 0}
newSize: {x: 0, y: 0}
adaptiveTilingThreshold: 0
drawMode: 0
adaptiveTiling: 0
m_AutoTiling: 0
serializedVersion: 2
m_Size: {x: 1.2, y: 2}
m_EdgeRadius: 0
--- !u!114 &4960688227238377219 --- !u!114 &4960688227238377219
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -7280,6 +7280,103 @@ MonoBehaviour:
BarrelClipping: 0.25 BarrelClipping: 0.25
Anamorphism: 0 Anamorphism: 0
BlendHint: 0 BlendHint: 0
--- !u!1 &378930082
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 378930085}
- component: {fileID: 378930084}
- component: {fileID: 378930083}
m_Layer: 24
m_Name: BossFightTrigger_ChaoFeng
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &378930083
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 378930082}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bd8a9d00a149c124a9bd90ffba663a32, type: 3}
m_Name:
m_EditorClassIdentifier:
_bossBrain: {fileID: 2029340551999249091}
_onBossFightStarted: {fileID: 11400000, guid: 6ac21fc2929c8ce4b9f56df680ad122b, type: 2}
_onBossFightToggled: {fileID: 11400000, guid: f367dc6d9a2848241b54799ce37f7288, type: 2}
_bossId: ChaoFeng
_playerLayers:
serializedVersion: 2
m_Bits: 512
--- !u!61 &378930084
BoxCollider2D:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 378930082}
m_Enabled: 1
m_Density: 1
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_ForceSendLayers:
serializedVersion: 2
m_Bits: 4294967295
m_ForceReceiveLayers:
serializedVersion: 2
m_Bits: 4294967295
m_ContactCaptureLayers:
serializedVersion: 2
m_Bits: 4294967295
m_CallbackLayers:
serializedVersion: 2
m_Bits: 4294967295
m_IsTrigger: 1
m_UsedByEffector: 0
m_UsedByComposite: 0
m_Offset: {x: 0, y: 0}
m_SpriteTilingProperty:
border: {x: 0, y: 0, z: 0, w: 0}
pivot: {x: 0, y: 0}
oldSize: {x: 0, y: 0}
newSize: {x: 0, y: 0}
adaptiveTilingThreshold: 0
drawMode: 0
adaptiveTiling: 0
m_AutoTiling: 0
serializedVersion: 2
m_Size: {x: 4, y: 6}
m_EdgeRadius: 0
--- !u!4 &378930085
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 378930082}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 87, y: 21, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!4 &379870868 stripped --- !u!4 &379870868 stripped
Transform: Transform:
m_CorrespondingSourceObject: {fileID: 8020630769765462792, guid: dadbcefa02b3d0f4ba27af93ff088166, type: 3} m_CorrespondingSourceObject: {fileID: 8020630769765462792, guid: dadbcefa02b3d0f4ba27af93ff088166, type: 3}
@@ -217899,6 +217996,74 @@ Transform:
- {fileID: 505494684} - {fileID: 505494684}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &2029340551999249090
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalPosition.x
value: 98
objectReference: {fileID: 0}
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalPosition.y
value: 21
objectReference: {fileID: 0}
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2025611111464161772, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7781161515165213226, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
propertyPath: m_Name
value: ENM_ChaoFeng
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
--- !u!114 &2029340551999249091 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 4739322141714049461, guid: e55e94346ed15ce40bc0ae5aa7771ea6, type: 3}
m_PrefabInstance: {fileID: 2029340551999249090}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d92d657c6bbdfe246a7333e04f79f8f7, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1660057539 &9223372036854775807 --- !u!1660057539 &9223372036854775807
SceneRoots: SceneRoots:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -217912,3 +218077,5 @@ SceneRoots:
- {fileID: 960547555} - {fileID: 960547555}
- {fileID: 445140214} - {fileID: 445140214}
- {fileID: 310446327} - {fileID: 310446327}
- {fileID: 2029340551999249090}
- {fileID: 378930085}
@@ -328,12 +328,12 @@ namespace BaseGames.Editor
var factory = MakeActionGroup(); var factory = MakeActionGroup();
factory.Add(MakeFactoryButton("ENM_ChaoFeng_Stats.asset", () => { CreateChaoFengStatsSO(); RefreshSOStatus(); })); factory.Add(MakeFactoryButton("ENM_ChaoFeng_Stats.asset", () => { CreateChaoFengStatsSO(); RefreshSOStatus(); }));
factory.Add(MakeFactoryButton("ENM_ChaoFeng_AnimConfig.asset",() => { CreateChaoFengAnimConfigSO(); RefreshSOStatus(); })); factory.Add(MakeFactoryButton("ENM_ChaoFeng_AnimConfig.asset",() => { CreateChaoFengAnimConfigSO(); RefreshSOStatus(); }));
foreach (var (abName, abId, soType, r, cd, w, ph) in ChaoFengAbilityDefs) foreach (var (abName, abId, soType, r, cd, w, ph, g) in ChaoFengAbilityDefs)
{ {
string cName = abName; string cId = abId; System.Type cType = soType; string cName = abName; string cId = abId; System.Type cType = soType;
float cR = r, cCd = cd, cW = w; int cPh = ph; float cR = r, cCd = cd, cW = w; int cPh = ph; bool cG = g;
factory.Add(MakeFactoryButton($"ABL_ChaoFeng_{cName}.asset", factory.Add(MakeFactoryButton($"ABL_ChaoFeng_{cName}.asset",
() => { CreateChaoFengAbilitySO(cName, cId, cType, cR, cCd, cW, cPh); RefreshSOStatus(); })); () => { CreateChaoFengAbilitySO(cName, cId, cType, cR, cCd, cW, cPh, cG); RefreshSOStatus(); }));
} }
root.Add(factory); root.Add(factory);
@@ -691,7 +691,7 @@ namespace BaseGames.Editor
private static void CreateChaoFengAbilitySO( private static void CreateChaoFengAbilitySO(
string abilityName, string abilityId, System.Type soType, string abilityName, string abilityId, System.Type soType,
float rangeRadius, float cooldown, float weight, int phase) float rangeRadius, float cooldown, float weight, int phase, bool requiresGrounded)
{ {
const string dir = "Assets/_Game/Data/Enemies/ChaoFeng/Abilities"; const string dir = "Assets/_Game/Data/Enemies/ChaoFeng/Abilities";
string name = $"ABL_ChaoFeng_{abilityName}"; string name = $"ABL_ChaoFeng_{abilityName}";
@@ -704,6 +704,9 @@ namespace BaseGames.Editor
? "入场演出,不进选招池" ? "入场演出,不进选招池"
: $"阶段 {phase} 招式;阶段可用性由 BossPhaseAbilityGate 配置"; : $"阶段 {phase} 招式;阶段可用性由 BossPhaseAbilityGate 配置";
so.cooldown = cooldown; so.cooldown = cooldown;
// 空中阶段的招必须放开这一项:选招器把 requiresGrounded 当硬门,
// Boss 浮空时 IsGrounded 恒为 false,留着默认 true 会让该招永远选不中。
so.requiresGrounded = requiresGrounded;
if (phase < 0) if (phase < 0)
{ {
@@ -727,25 +730,27 @@ namespace BaseGames.Editor
/// (见放置工具 PlaceChaoFeng),这里只记录供说明文本使用。 /// (见放置工具 PlaceChaoFeng),这里只记录供说明文本使用。
/// rangeRadius 必须 &gt; 0category==Attack 且射程为 0 的招永远够不着玩家, /// rangeRadius 必须 &gt; 0category==Attack 且射程为 0 的招永远够不着玩家,
/// EnemyAbilitySO.Validate 与 EnemyBase.BuildAttackSelector 都会显式报错。 /// EnemyAbilitySO.Validate 与 EnemyBase.BuildAttackSelector 都会显式报错。
/// grounded 是选招器的硬门:阶段 1 是空中阶段(Boss 浮空,IsGrounded 恒 false),
/// 该阶段的招必须为 false,否则永远选不中,空中阶段会站着不打。
/// </summary> /// </summary>
private static readonly (string name, string id, System.Type soType, private static readonly (string name, string id, System.Type soType,
float rangeRadius, float cooldown, float weight, int phase)[] float rangeRadius, float cooldown, float weight, int phase, bool grounded)[]
ChaoFengAbilityDefs = ChaoFengAbilityDefs =
{ {
("Intro", "chaofeng_intro", typeof(PlayClipAbilitySO), 0f, 0f, 0f, -1), ("Intro", "chaofeng_intro", typeof(PlayClipAbilitySO), 0f, 0f, 0f, -1, true),
("Boomerang", "boomerang", typeof(PlayClipAbilitySO), 9f, 4.0f, 1.0f, 0), ("Boomerang", "boomerang", typeof(PlayClipAbilitySO), 9f, 4.0f, 1.0f, 0, true),
("FanCombo", "fan_combo", typeof(EnemyAbilitySO), 2.5f, 2.5f, 1.5f, 0), ("FanCombo", "fan_combo", typeof(EnemyAbilitySO), 2.5f, 2.5f, 1.5f, 0, true),
("TornadoSmall", "tornado_small", typeof(PlayClipAbilitySO), 8f, 3.5f, 1.2f, 0), ("TornadoSmall", "tornado_small", typeof(PlayClipAbilitySO), 8f, 3.5f, 1.2f, 0, true),
("TornadoLarge", "tornado_large", typeof(PlayClipAbilitySO), 12f, 6.0f, 0.8f, 0), ("TornadoLarge", "tornado_large", typeof(PlayClipAbilitySO), 12f, 6.0f, 0.8f, 0, true),
("WindStone", "wind_stone", typeof(PlayClipAbilitySO), 12f, 3.0f, 1.0f, 1), ("WindStone", "wind_stone", typeof(PlayClipAbilitySO), 12f, 3.0f, 1.0f, 1, false),
}; };
private static void CreateAllChaoFengSOs() private static void CreateAllChaoFengSOs()
{ {
CreateChaoFengStatsSO(); CreateChaoFengStatsSO();
CreateChaoFengAnimConfigSO(); CreateChaoFengAnimConfigSO();
foreach (var (n, id, t, r, cd, w, ph) in ChaoFengAbilityDefs) foreach (var (n, id, t, r, cd, w, ph, g) in ChaoFengAbilityDefs)
CreateChaoFengAbilitySO(n, id, t, r, cd, w, ph); CreateChaoFengAbilitySO(n, id, t, r, cd, w, ph, g);
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
EditorUtility.DisplayDialog("创建完成", EditorUtility.DisplayDialog("创建完成",
"全部嘲风 SO 已创建(已存在的跳过)。\n" + "全部嘲风 SO 已创建(已存在的跳过)。\n" +
@@ -825,7 +830,7 @@ namespace BaseGames.Editor
("ENM_ChaoFeng_Stats", FindAtPath<EnemyStatsSO>($"{dir}/ENM_ChaoFeng_Stats.asset")), ("ENM_ChaoFeng_Stats", FindAtPath<EnemyStatsSO>($"{dir}/ENM_ChaoFeng_Stats.asset")),
("ENM_ChaoFeng_AnimConfig",FindAtPath<EnemyAnimationConfigSO>($"{dir}/ENM_ChaoFeng_AnimConfig.asset")), ("ENM_ChaoFeng_AnimConfig",FindAtPath<EnemyAnimationConfigSO>($"{dir}/ENM_ChaoFeng_AnimConfig.asset")),
}; };
foreach (var (abName, _, _, _, _, _, _) in ChaoFengAbilityDefs) foreach (var (abName, _, _, _, _, _, _, _) in ChaoFengAbilityDefs)
checks.Add(($"ABL_ChaoFeng_{abName}", checks.Add(($"ABL_ChaoFeng_{abName}",
FindAtPath<EnemyAbilitySO>($"{ablDir}/ABL_ChaoFeng_{abName}.asset"))); FindAtPath<EnemyAbilitySO>($"{ablDir}/ABL_ChaoFeng_{abName}.asset")));
@@ -302,6 +302,7 @@ namespace BaseGames.Editor
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go); EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go); EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图) GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图)
GetOrAddComponent<EnemyLocomotion>(go); // 移动执行器:EnemyBase.Awake 必须找得到,否则 AI 图的移动意图无处落地
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go); PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
var (hurtBox, bodyContact, contactHitBox) = var (hurtBox, bodyContact, contactHitBox) =
@@ -445,6 +446,7 @@ namespace BaseGames.Editor
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go); EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go); EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图) GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图)
GetOrAddComponent<EnemyLocomotion>(go); // 移动执行器:EnemyBase.Awake 必须找得到,否则 AI 图的移动意图无处落地
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go); PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
var (hurtBox, bodyContact, contactHitBox) = var (hurtBox, bodyContact, contactHitBox) =
@@ -493,9 +495,7 @@ namespace BaseGames.Editor
SetupPerceptionSystemSlots(sensorHub, new[] { "aggro", "los" }, report); SetupPerceptionSystemSlots(sensorHub, new[] { "aggro", "los" }, report);
GetOrAddComponent<EnemyLocomotion>(go); // BrainGraph AI:挂载决策组件并绑定 AI 配方资产
// BrainGraph AI:挂载决策组件并绑定 AI 配方资产(取代旧的 Opsive BehaviorTree
var brain = GetOrAddComponent<EnemyAiBrain>(go); var brain = GetOrAddComponent<EnemyAiBrain>(go);
var recipe = AssetDatabase.LoadAssetAtPath<PerceptionRecipeSO>( var recipe = AssetDatabase.LoadAssetAtPath<PerceptionRecipeSO>(
"Assets/_Game/Data/Enemies/E001/ENM_E001_Ai.asset"); "Assets/_Game/Data/Enemies/E001/ENM_E001_Ai.asset");
@@ -550,6 +550,7 @@ namespace BaseGames.Editor
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go); EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go); EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图) GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图)
GetOrAddComponent<EnemyLocomotion>(go); // 移动执行器:EnemyBase.Awake 必须找得到,否则 AI 图的移动意图无处落地
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go); PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
// HurtBox + ContactDamageZone(身体接触伤害常驻开启;HurtBox 悬挂期外关闭见下) // HurtBox + ContactDamageZone(身体接触伤害常驻开启;HurtBox 悬挂期外关闭见下)
@@ -651,6 +652,7 @@ namespace BaseGames.Editor
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go); EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go); EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图) GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图)
GetOrAddComponent<EnemyLocomotion>(go); // 移动执行器:EnemyBase.Awake 必须找得到,否则 AI 图的移动意图无处落地
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go); PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
var (hurtBox, bodyContact, contactHitBox) = var (hurtBox, bodyContact, contactHitBox) =
@@ -741,6 +743,7 @@ namespace BaseGames.Editor
EnemyFeedback feedback = GetOrAddComponent<EnemyFeedback>(go); EnemyFeedback feedback = GetOrAddComponent<EnemyFeedback>(go);
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go); EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图) GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图)
GetOrAddComponent<EnemyLocomotion>(go); // 移动执行器:EnemyBase.Awake 必须找得到,否则 AI 图的移动意图无处落地
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go); PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
var (hurtBox, bodyContact, contactHitBox) = var (hurtBox, bodyContact, contactHitBox) =
@@ -871,6 +874,7 @@ namespace BaseGames.Editor
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go); EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go); EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图) GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图)
GetOrAddComponent<EnemyLocomotion>(go); // 移动执行器:EnemyBase.Awake 必须找得到,否则 AI 图的移动意图无处落地
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go); PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
var (hurtBox, bodyContact, contactHitBox) = var (hurtBox, bodyContact, contactHitBox) =
@@ -982,6 +986,7 @@ namespace BaseGames.Editor
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go); EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go); EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图) GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图)
GetOrAddComponent<EnemyLocomotion>(go); // 移动执行器:EnemyBase.Awake 必须找得到,否则 AI 图的移动意图无处落地
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go); PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
var (hurtBox, bodyContact, contactHitBox) = var (hurtBox, bodyContact, contactHitBox) =
@@ -1084,6 +1089,10 @@ namespace BaseGames.Editor
EnemyFeedback feedback = GetOrAddComponent<EnemyFeedback>(go); EnemyFeedback feedback = GetOrAddComponent<EnemyFeedback>(go);
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go); EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图) GetOrAddComponent<BaseGames.Enemies.Navigation.GroundNavigator>(go); // 地面导航(直接移动,无寻路图)
// 移动执行器:AI 图的移动意图(Idle/Face/Approach)全靠它落地。
// 少了它 EnemyBase.Awake 就报「未找到 EnemyLocomotion」,且 Locomotion 为 null
// 建图时 AiStateFragments.ApplyLocomotion 会 NREAiRuntime 构造失败 → Boss 完全不动。
GetOrAddComponent<EnemyLocomotion>(go);
EnemyAiBrain brain = GetOrAddComponent<EnemyAiBrain>(go); EnemyAiBrain brain = GetOrAddComponent<EnemyAiBrain>(go);
BossPhaseAbilityGate phaseGate = GetOrAddComponent<BossPhaseAbilityGate>(go); BossPhaseAbilityGate phaseGate = GetOrAddComponent<BossPhaseAbilityGate>(go);
ChaoFengFloatController floatCtrl = GetOrAddComponent<ChaoFengFloatController>(go); ChaoFengFloatController floatCtrl = GetOrAddComponent<ChaoFengFloatController>(go);
@@ -1094,16 +1103,16 @@ namespace BaseGames.Editor
var (hurtBox, bodyContact, contactHitBox) = var (hurtBox, bodyContact, contactHitBox) =
SetupHurtAndContactBoxes(go, size, report); SetupHurtAndContactBoxes(go, size, report);
// Phase1 攻击 HitBox(默认禁用;由能力按 EnemyAttackSO.hitBoxSlot 归一化时机开关)。 // 近战攻击 HitBox(默认禁用;由 MeleeAttackAbility 按 EnemyAttackSO.hitBoxSlot 归一化时机开关)。
// 计划:挥扇三连 FanCombo ×3 + 龙卷接触 Tornado。 // 只有挥扇三连需要 Boss 自身的判定;回旋扇 / 龙卷 / 风石都是弹体招,
// 判定随 SpawnProjectile 动画事件生成的弹体走,Boss 身上不留对应 HitBox
// (留一个无人引用的 HitBox 会让作者误以为该招判定挂在 Boss 身上)。
HitBox fan1 = CreateDisabledHitBox(go.transform, "Phase1_FanCombo_HitBox_1", "EnemyHitBox", HitBox fan1 = CreateDisabledHitBox(go.transform, "Phase1_FanCombo_HitBox_1", "EnemyHitBox",
true, report, size: new Vector2(1.0f, 0.5f)); true, report, size: new Vector2(1.0f, 0.5f));
HitBox fan2 = CreateDisabledHitBox(go.transform, "Phase1_FanCombo_HitBox_2", "EnemyHitBox", HitBox fan2 = CreateDisabledHitBox(go.transform, "Phase1_FanCombo_HitBox_2", "EnemyHitBox",
true, report, size: new Vector2(1.0f, 0.5f)); true, report, size: new Vector2(1.0f, 0.5f));
HitBox fan3 = CreateDisabledHitBox(go.transform, "Phase1_FanCombo_HitBox_3", "EnemyHitBox", HitBox fan3 = CreateDisabledHitBox(go.transform, "Phase1_FanCombo_HitBox_3", "EnemyHitBox",
true, report, size: new Vector2(1.2f, 0.6f)); true, report, size: new Vector2(1.2f, 0.6f));
HitBox tornadoHB = CreateDisabledHitBox(go.transform, "Phase1_Tornado_HitBox", "EnemyHitBox",
true, report, size: new Vector2(0.6f, 1.2f));
// 弹体发射点(Phase1 回旋扇 / 龙卷;Phase2 风石) // 弹体发射点(Phase1 回旋扇 / 龙卷;Phase2 风石)
Transform boomerangMuzzleT = GetOrCreateChild(go.transform, "BoomerangMuzzle"); Transform boomerangMuzzleT = GetOrCreateChild(go.transform, "BoomerangMuzzle");
@@ -1212,7 +1221,7 @@ namespace BaseGames.Editor
Object dmgSrc = FindFirstAsset("CMB_DS_BossBody", "CMB_DS_EnemyBody"); Object dmgSrc = FindFirstAsset("CMB_DS_BossBody", "CMB_DS_EnemyBody");
if (dmgSrc != null) if (dmgSrc != null)
{ {
foreach (var hb in new[] { fan1, fan2, fan3, tornadoHB, contactHitBox }) foreach (var hb in new[] { fan1, fan2, fan3, contactHitBox })
if (hb != null) AssignReference(hb, "_defaultSource", dmgSrc, report); if (hb != null) AssignReference(hb, "_defaultSource", dmgSrc, report);
} }
@@ -1235,6 +1244,75 @@ namespace BaseGames.Editor
MarkDirtyAndLog("Boss 嘲风 (ChaoFeng)", go, report); MarkDirtyAndLog("Boss 嘲风 (ChaoFeng)", go, report);
} }
[MenuItem("BaseGames/Scene/Place/Boss 开战触发区 (嘲风)", priority = 118)]
public static void PlaceChaoFengFightTrigger() => PlaceBossFightTrigger("ChaoFeng");
/// <summary>
/// 放置 Boss 开战触发区:玩家进入即广播开战事件并让 Boss 决策层进战。
/// 没有它,Boss 会一直停在静置态——开战事件频道此前全项目零发送方。
/// </summary>
/// <param name="bossId">
/// Boss id。既写进触发器的 <c>_bossId</c>BGM / 血条按它定位 Boss),
/// 也用来在活动场景里定位目标 Boss——按 <c>EnemyAiBrain._definitionId</c> 匹配。
/// </param>
public static void PlaceBossFightTrigger(string bossId)
{
var report = new List<string>();
int undoGroup = Undo.GetCurrentGroup();
Undo.SetCurrentGroupName("Place Boss Fight Trigger");
GameObject go = new GameObject($"BossFightTrigger_{bossId}");
Undo.RegisterCreatedObjectUndo(go, "Place Boss Fight Trigger");
go.transform.position = GetDropPosition();
SetLayer(go, "TriggerZone", report);
// 碰撞体必须先于 BossFightTrigger 挂上:该组件标了 [RequireComponent(typeof(Collider2D))]
// 而 Collider2D 是抽象类,Unity 补不出来,AddComponent 会返回真正的 null。
BoxCollider2D col = GetOrAddComponent<BoxCollider2D>(go);
col.isTrigger = true;
col.size = new Vector2(4f, 6f); // 门口尺寸占位,按竞技场入口在 Inspector 调整
BossFightTrigger trigger = GetOrAddComponent<BossFightTrigger>(go);
AssignString(trigger, "_bossId", bossId, report);
AssignLayerMask(trigger, "_playerLayers", "Player", report);
AssignAsset(trigger, "_onBossFightStarted", report, true, "EVT_BossFightStarted");
// 开关频道:资产名叫 EVT_BossFightEnded,但实际是「战斗中 true/false」的开关,
// BGMController 与 BossHPBar 绑的也是它。名字与用途不符是既存问题,此处沿用同一资产。
AssignAsset(trigger, "_onBossFightToggled", report, true, "EVT_BossFightEnded");
// 目标 Boss:按 EnemyAiBrain._definitionId 在活动场景里精确匹配,不做名字模糊猜测。
// 匹配不到(或匹配到多个)一律如实报告,不塞一个凑数的引用——
// 漏绑时 BossFightTrigger.Awake 也会再报一次并停用自己。
var matches = new List<EnemyAiBrain>();
foreach (var root in UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().GetRootGameObjects())
foreach (var b in root.GetComponentsInChildren<EnemyAiBrain>(true))
if (new SerializedObject(b).FindProperty("_definitionId")?.stringValue == bossId)
matches.Add(b);
if (matches.Count == 1)
{
AssignReference(trigger, "_bossBrain", matches[0], report);
report.Add($"[OK] _bossBrain → {matches[0].name}_definitionId={bossId}");
}
else if (matches.Count == 0)
{
report.Add($"✗ 活动场景里找不到 _definitionId={bossId} 的 EnemyAiBrain" +
"_bossBrain 未绑定。请先放置该 Boss,再重跑本操作。");
}
else
{
report.Add($"✗ 活动场景里有 {matches.Count} 个 _definitionId={bossId} 的 EnemyAiBrain" +
"无法确定目标,_bossBrain 未绑定。请先清理重复的 Boss。");
}
report.Add("★ 把触发区拖到竞技场入口并按门口尺寸调整 BoxCollider2D。只触发一次。");
Undo.CollapseUndoOperations(undoGroup);
Selection.activeGameObject = go;
MarkDirtyAndLog($"Boss 开战触发区 ({bossId})", go, report);
}
// ══ 敌人放置辅助方法 ═══════════════════════════════════════════════════ // ══ 敌人放置辅助方法 ═══════════════════════════════════════════════════
/// <summary> /// <summary>
@@ -67,10 +67,26 @@ namespace BaseGames.Enemies
public Vector2 LastKnown => _lastKnown; public Vector2 LastKnown => _lastKnown;
// ---- ICombatant ---- // ---- ICombatant ----
/// <summary>
/// 执行指定 id 的能力。解析不到该 id 一律显式报错——
/// 建图期 <c>AiStateFragments.Ability/AbilityOnce</c> 已挡掉空 id
/// 所以运行期解析不到只可能是漏挂能力组件或 SO 上的 abilityId 写错,没有合法情形。
/// 静默返回 false 会让「能力态进入后什么都不做、IsAbilityRunning 恒假、
/// 完成条件立刻成立」表现为"演出被跳过"却零报错(CLAUDE.md 第 6 条)。
/// 用 LogError 而非抛异常:这是每帧路径,抛异常会打断整个 AiRuntime.Tick
/// 让一个漏配的敌人拖垮整场战斗。
/// </summary>
public bool UseAbility(string abilityId) public bool UseAbility(string abilityId)
{ {
var a = _enemy.Abilities?.Get(abilityId); var a = _enemy.Abilities?.Get(abilityId);
return a != null && a.Execute(); if (a == null)
{
Debug.LogError($"[EnemyBrainContext] '{_enemy.name}' 的 AI 图请求能力 " +
$"'{abilityId}',但该敌人身上没有这个能力组件。" +
"请检查能力组件是否挂载、其 EnemyAbilitySO 的 abilityId 是否一致。", _enemy);
return false;
}
return a.Execute();
} }
public bool IsAbilityRunning(string abilityId = null) public bool IsAbilityRunning(string abilityId = null)
{ {
@@ -86,6 +86,16 @@ namespace BaseGames.Enemies
if (_arenaAnchors == null) _arenaAnchors = GetComponentInChildren<BossArenaAnchors>(true); if (_arenaAnchors == null) _arenaAnchors = GetComponentInChildren<BossArenaAnchors>(true);
} }
// 初始阶段的招池必须在第一次选招前就位。
// ApplyPhase 此前只在 EnterPhase(阶段切换)与 OnSpawn(对象池复用)里调用,
// 而直接摆在场景里的 Boss 两条路径都不走——开局时后续阶段的招式仍是 enabled,
// 会混进阶段 0 的候选池。放在 Start:此时各能力组件的 Awake 均已执行完毕。
protected override void Start()
{
base.Start();
_phaseGate?.ApplyPhase(_currentPhase);
}
protected override void OnEnable() protected override void OnEnable()
{ {
base.OnEnable(); base.OnEnable();