Files
zeling_v2/Assets/_Game/Scripts/Enemies/Abilities/ContactChaseAbility.cs
Joywayer 06048c966a feat: Add HurtBoxOwnerGuard to prevent multiple damage registrations from the same HitBox activation
- Implemented HurtBoxOwnerGuard to ensure that multiple HurtBoxes on the same character do not register damage multiple times during a single HitBox activation.
- Added custom editor for HitBox to facilitate the creation of shape colliders with HitBoxColliderProxy.
- Introduced PhysicsPerceptionSystem for enemy perception, supporting multiple detection modes including RangeCircle, BatchLOS, FanCast, and BoxCast.
- Created EnemyPatrolZone to define patrol and chase areas for enemies, allowing for shared zones among multiple enemies.
- Added BD_IsOutsideZone conditional task for Behavior Designer to check if an enemy or player is outside a defined patrol zone.
2026-06-02 16:10:44 +08:00

64 lines
2.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections;
using Animancer;
using UnityEngine;
namespace BaseGames.Enemies.Abilities
{
/// <summary>
/// 循环追击 + 体接触伤害能力。
/// 追击期间每帧更新 MoveTo失去感知后收招退出并恢复巡逻状态。
/// 可复用于任何需要"追击+接触伤害循环"的敌人。
/// </summary>
public class ContactChaseAbility : EnemyAbilityBase
{
[Header("动画")]
[SerializeField] private ClipTransition _loopClip;
[SerializeField] private ClipTransition _endClip;
[Header("感知与接触伤害")]
[SerializeField] private BodyContactDamage _contactDamage;
[Tooltip("用于追击感知判断的传感器槽位名,通常为 \"aggro\"")]
[SerializeField] private string _aggroSlotName = "aggro";
protected override IEnumerator ExecuteCoroutine()
{
Phase = AbilityRunState.Active;
if (_loopClip.Clip != null)
_animancer.Play(_loopClip);
if (_contactDamage != null)
_contactDamage.enabled = true;
while (true)
{
if (_enemy.PlayerTransform == null) break;
if (_enemy.SensorHub != null && !_enemy.SensorHub.IsDetecting(_aggroSlotName, _enemy.PlayerTransform.gameObject))
break;
_enemy.MoveTo(_enemy.PlayerTransform.position);
yield return null;
}
if (_contactDamage != null)
_contactDamage.enabled = false;
_enemy.StopMovement();
if (_endClip.Clip != null)
{
_animancer.Play(_endClip);
yield return EnemyAbilityWaits.Get(_endClip.Clip.length);
}
_enemy.SetAiPhase(AiPhase.Patrol);
}
protected override void OnInterrupted(InterruptReason reason)
{
if (_contactDamage != null)
_contactDamage.enabled = false;
}
}
}