diff --git a/Assets/_Game/Scripts/Enemies/Abilities/Configs.meta b/Assets/_Game/Scripts/Enemies/Abilities/Configs.meta
new file mode 100644
index 00000000..f3dc91ad
--- /dev/null
+++ b/Assets/_Game/Scripts/Enemies/Abilities/Configs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: b20e3c83afca062429b9ce14ea5172c5
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/_Game/Scripts/Enemies/Abilities/Configs/ContactChaseAbilitySO.cs b/Assets/_Game/Scripts/Enemies/Abilities/Configs/ContactChaseAbilitySO.cs
new file mode 100644
index 00000000..65f2817c
--- /dev/null
+++ b/Assets/_Game/Scripts/Enemies/Abilities/Configs/ContactChaseAbilitySO.cs
@@ -0,0 +1,19 @@
+using Animancer;
+using UnityEngine;
+
+namespace BaseGames.Enemies.Abilities
+{
+ /// ContactChaseAbility 的配置:起手/循环/收招动画 + 冲刺速度。
+ [CreateAssetMenu(menuName = "BaseGames/Enemies/Abilities/Contact Chase Ability", fileName = "ABL_")]
+ public class ContactChaseAbilitySO : EnemyAbilitySO
+ {
+ [Header("动画(起手 / 循环 / 收招)")]
+ public ClipTransition startClip; // Skill_Start:张口(一次性)
+ public ClipTransition loopClip; // Skill_Loop:快速爬行追击(循环)
+ public ClipTransition endClip; // Skill_End:收招(一次性)
+
+ [Header("冲刺")]
+ [Tooltip("冲刺速度;<=0 时回退用 EnemyStatsSO.RunSpeed(追击速度)")]
+ public float dashSpeed = 0f;
+ }
+}
diff --git a/Assets/_Game/Scripts/Enemies/Abilities/Configs/ContactChaseAbilitySO.cs.meta b/Assets/_Game/Scripts/Enemies/Abilities/Configs/ContactChaseAbilitySO.cs.meta
new file mode 100644
index 00000000..90f5d622
--- /dev/null
+++ b/Assets/_Game/Scripts/Enemies/Abilities/Configs/ContactChaseAbilitySO.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ffa0a2f8565d1ea4395d219f41ae4226
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/_Game/Scripts/Enemies/Abilities/ContactChaseAbility.cs b/Assets/_Game/Scripts/Enemies/Abilities/ContactChaseAbility.cs
index 8f997877..b09ea0d4 100644
--- a/Assets/_Game/Scripts/Enemies/Abilities/ContactChaseAbility.cs
+++ b/Assets/_Game/Scripts/Enemies/Abilities/ContactChaseAbility.cs
@@ -13,20 +13,21 @@ namespace BaseGames.Enemies.Abilities
///
public class ContactChaseAbility : EnemyAbilityBase
{
- [Header("动画(起手 / 循环 / 收招)")]
- [SerializeField] private ClipTransition _startClip; // Skill_Start:张口(一次性)
- [SerializeField] private ClipTransition _loopClip; // Skill_Loop:快速爬行追击(循环)
- [SerializeField] private ClipTransition _endClip; // Skill_End:收招(一次性)
-
[Header("接触伤害")]
[SerializeField] private BodyContactDamage _contactDamage;
- [Header("冲刺")]
- [Tooltip("冲刺速度;<=0 时回退用 EnemyStatsSO.RunSpeed(追击速度)")]
- [SerializeField] private float _dashSpeed = 0f;
+ private ContactChaseAbilitySO _cfg;
+
+ protected override void Awake()
+ {
+ base.Awake();
+ _cfg = ResolveConfig();
+ }
protected override IEnumerator ExecuteCoroutine()
{
+ if (_cfg == null) yield break;
+
Phase = AbilityRunState.Active;
_enemy.SetEngaged(true);
@@ -44,20 +45,20 @@ namespace BaseGames.Enemies.Abilities
}
// 起手:张口(一次性)。期间静止、不伤人;锁住动画防被步态覆盖。
- if (_startClip.Clip != null)
+ if (_cfg.startClip.Clip != null)
{
- _enemy.LockAnim(_startClip.Clip.length);
- _animancer.Play(_startClip);
- yield return EnemyAbilityWaits.Get(_startClip.Clip.length);
+ _enemy.LockAnim(_cfg.startClip.Clip.length);
+ _animancer.Play(_cfg.startClip);
+ yield return EnemyAbilityWaits.Get(_cfg.startClip.Clip.length);
}
// 冲刺速度:优先能力配置的 _dashSpeed,否则回退 Stats.RunSpeed
- float speed = _dashSpeed > 0f ? _dashSpeed
+ float speed = _cfg.dashSpeed > 0f ? _cfg.dashSpeed
: (_enemy.Stats != null ? _enemy.Stats.RunSpeed : 0f);
// 冲刺:朝该方向直冲、接触伤害开、播 Skill_Loop,直到撞墙/到边缘或玩家消失即停。
- if (_loopClip.Clip != null)
- _animancer.Play(_loopClip);
+ if (_cfg.loopClip.Clip != null)
+ _animancer.Play(_cfg.loopClip);
if (_contactDamage != null)
_contactDamage.enabled = true;
@@ -92,20 +93,20 @@ namespace BaseGames.Enemies.Abilities
// 丢失目标 = AI 主动退出追击态(ExternalRequest) → 播收招 Skill_End;
// 受击/死亡/硬直等硬打断不播收招。协程已停,fire-and-forget;动画锁保证 Skill_End
// 在其时长内不被巡逻步态盖掉。
- if (reason == InterruptReason.ExternalRequest && _endClip.Clip != null)
+ if (reason == InterruptReason.ExternalRequest && _cfg != null && _cfg.endClip.Clip != null)
{
- _enemy.LockAnim(_endClip.Clip.length);
- _animancer.Play(_endClip);
+ _enemy.LockAnim(_cfg.endClip.Clip.length);
+ _animancer.Play(_cfg.endClip);
}
Cleanup();
}
private IEnumerator PlaySkillEnd()
{
- if (_endClip.Clip == null) yield break;
- _enemy.LockAnim(_endClip.Clip.length);
- _animancer.Play(_endClip);
- yield return EnemyAbilityWaits.Get(_endClip.Clip.length);
+ if (_cfg == null || _cfg.endClip.Clip == null) yield break;
+ _enemy.LockAnim(_cfg.endClip.Clip.length);
+ _animancer.Play(_cfg.endClip);
+ yield return EnemyAbilityWaits.Get(_cfg.endClip.Clip.length);
}
private void DisableContact()