Files
zeling_v2/Assets/_Game/Scripts/Enemies/AI/BD_Patrol.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

70 lines
2.6 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.
#if GRAPH_DESIGNER
using UnityEngine;
using Opsive.BehaviorDesigner.Runtime.Tasks;
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
using BaseGames.Enemies;
namespace BaseGames.Enemies.AI
{
/// <summary>
/// BD Action来回踱步巡逻——持续向当前方向移动遇墙或悬崖时自动翻转方向。
/// 转向检测通过 <see cref="EnemyMovement.IsWallAhead"/> / <see cref="EnemyMovement.IsLedgeAhead"/>
/// 进行;这两项是 EnemyMovement 内置的物理射线检测不属于感知系统PhysicsPerceptionSystem
///
/// 若需要按预设路点顺序巡逻,请使用 <see cref="BD_PatrolWaypoints"/>(支持 Transform 引用和内联坐标)。
/// </summary>
[TaskName("Patrol (Pace)")]
[TaskCategory("BaseGames/Enemy/Movement")]
[TaskDescription("来回踱步巡逻:遇墙或悬崖自动翻转方向(通过 EnemyMovement 物理射线检测,无需感知槽)")]
public class BD_Patrol : Action
{
private EnemyBase _enemy;
private EnemyMovement _movement;
private float _dir = 1f;
private float _flipCooldown; // 翻转后短暂冷却,等待射线刷新到新朝向
public override void OnAwake()
{
_enemy = GetComponent<EnemyBase>();
_movement = _enemy?.Movement;
}
public override void OnStart()
{
_enemy?.SetAiPhase(AiPhase.Patrol);
// 与敌人实际朝向同步,防止任务重入时 _dir 与朝向不符(如战斗后朝向已改变)
if (_movement != null)
_dir = _movement.FacingDirection;
_flipCooldown = 0f;
}
public override TaskStatus OnUpdate()
{
if (_enemy == null) return TaskStatus.Failure;
// 翻转冷却期间跳过物理检测(等待射线在新朝向完成刷新)
if (_flipCooldown > 0f)
_flipCooldown -= Time.deltaTime;
else if (ShouldFlip())
{
_dir = -_dir;
_flipCooldown = 0.1f; // ~6 帧缓冲60 fps防止射线残留信号导致抖动
}
_enemy.MoveInDirection(_dir);
return TaskStatus.Running;
}
public override void OnEnd() => _enemy?.StopMovement();
private bool ShouldFlip()
{
// 转身进行中时不重复检测,防止 _dir 在转身期间被残留信号反复翻转
if (_movement == null || _movement.IsTurning) return false;
return _movement.IsWallAhead || _movement.IsLedgeAhead;
}
}
}
#endif