using System.Collections; using UnityEngine; using BaseGames.Combat; namespace BaseGames.Enemies.Abilities { /// /// 挂顶下落能力:怪物初始挂在天花板(kinematic,重力 0)。能力触发后: /// 1. 切换为 dynamic + 恢复重力 /// 2. 自由落体到接触地面 /// 3. 落地播放 AoE HitBox + 砸地反馈 /// [RequireComponent(typeof(Rigidbody2D))] public sealed class CeilingDropAbility : EnemyAbilityBase { [Header("下落")] [SerializeField] private float _fallGravityScale = 3.5f; [SerializeField] private float _maxFallTime = 3f; [SerializeField] private LayerMask _groundMask; [Header("落地")] [SerializeField] private HitBox _landingHitBox; [SerializeField] private float _hitBoxActiveTime = 0.2f; [SerializeField] private float _recoveryTime = 0.4f; private Rigidbody2D _rb; private RigidbodyType2D _origBodyType; private float _origGravityScale; protected override void Awake() { base.Awake(); _rb = GetComponentInParent(); } protected override IEnumerator ExecuteCoroutine() { if (_rb == null) yield break; var atk = (_config.attackSequence != null && _config.attackSequence.Length > 0) ? _config.attackSequence[0] : null; Phase = AbilityRunState.Active; // 切换到动态 + 恢复重力 _origBodyType = _rb.bodyType; _origGravityScale = _rb.gravityScale; _rb.bodyType = RigidbodyType2D.Dynamic; _rb.gravityScale = _fallGravityScale; _rb.velocity = Vector2.zero; float t = 0f; while (t < _maxFallTime) { t += Time.fixedDeltaTime; yield return new WaitForFixedUpdate(); if (t > 0.05f && IsGrounded()) break; } _rb.velocity = Vector2.zero; if (_landingHitBox != null) { _landingHitBox.Activate(atk != null ? atk.damageSource : null, _transform); yield return EnemyAbilityWaits.Get(_hitBoxActiveTime); _landingHitBox.Deactivate(); } yield return EnemyAbilityWaits.Get(_recoveryTime); // 落地后不恢复挂顶状态(一般转为地面行为),保持动态 Rigidbody } private bool IsGrounded() { var hit = Physics2D.Raycast(_rb.position, Vector2.down, 0.6f, _groundMask); return hit.collider != null; } protected override void OnInterrupted(InterruptReason reason) { if (_landingHitBox != null && _landingHitBox.IsActive) _landingHitBox.Deactivate(); // 中断时恢复 Rigidbody 原始状态,防止物理参数泄漏 if (_rb != null) { _rb.velocity = Vector2.zero; _rb.bodyType = _origBodyType; _rb.gravityScale = _origGravityScale; } } } }