feat: Enhance Physics Perception System with new detection modes and performance optimizations

- Updated PhysicsPerceptionSystem to support seven detection modes: RangeCircle, BatchLOS, FanCast, BoxCast, Sight, RayCast, and TriggerZone.
- Improved documentation for each detection mode, including performance optimization strategies.
- Introduced PerceptionTriggerProxy for event-driven detection in TriggerZone slots.
- Added SightBatchSystem to manage Sight slots efficiently, reducing CPU spikes during high enemy counts.
- Updated SensorSlotNames to reflect new detection modes and their purposes.
- Enhanced internal logic for detecting targets and managing detection events.
This commit is contained in:
2026-06-02 23:18:20 +08:00
parent 150440495d
commit d27ae9407d
17 changed files with 1946 additions and 335 deletions

View File

@@ -18,7 +18,7 @@ namespace BaseGames.Enemies
/// ⚠️ _nav 字段类型为 IPathAgent在 BaseGames.Enemies.Navigation 中实现具体类)。
/// 实现 IPoolable配合 PooledObject 支持对象池复用,避免频繁 Destroy/Instantiate。
/// </summary>
public class EnemyBase : MonoBehaviour, IDamageable, ILOSRequester, IPoolable
public class EnemyBase : MonoBehaviour, IDamageable, IPoolable
{
[Header("标识")]
[SerializeField] private string _enemyId; // 任务系统 / Boss 进程追踪用,如 "Enemy_SpiderGuard"
@@ -286,11 +286,14 @@ namespace BaseGames.Enemies
public virtual bool IsPlayerInRange(float range)
=> _stats != null && _stats.SqrDistanceToPlayer <= range * range;
/// <summary>原始视线检测结果(BatchLOSSystem 写入,无感知延迟修正)。</summary>
public bool HasLineOfSight => _losResult;
/// <summary>视线检测结果(由 PhysicsPerceptionSystem 的 LOS / Sight slot 提供)。</summary>
public bool HasLineOfSight =>
_sensorHub != null &&
(_sensorHub.HasAnyDetection(Perception.SensorSlotNames.LOS) ||
_sensorHub.HasAnyDetection(Perception.SensorSlotNames.Sight));
public virtual bool IsPlayerVisible()
=> _threatAssessor != null ? _threatAssessor.IsThreatDetected : _losResult;
=> _threatAssessor != null ? _threatAssessor.IsThreatDetected : HasLineOfSight;
public virtual void FacePlayer()
{
@@ -644,31 +647,16 @@ namespace BaseGames.Enemies
protected virtual void OnEnable()
{
_onPlayerSpawned?.Subscribe(SetPlayerTransform).AddTo(_subs);
Core.ServiceLocator.GetOrDefault<AI.BatchLOSSystem>()?.Register(this);
}
protected virtual void OnDisable()
{
Core.ServiceLocator.GetOrDefault<AI.BatchLOSSystem>()?.Unregister(this);
_subs.Clear();
}
protected virtual void OnDestroy() { }
// LOS 缓存BatchLOSSystem 写入;降级时由 3 帧节流 Raycast 写入)
private bool _losResult;
// ── ILOSRequester ──────────────────────────────────────────────────
public Vector2 LOSOrigin => (Vector2)transform.position + _statsSO.EyeOffset;
public Vector2 LOSTarget => _playerTransform != null
? (Vector2)_playerTransform.position
: (Vector2)transform.position;
public LayerMask LOSBlockingMask => _statsSO.LOSBlockingMask;
public void ReceiveLOSResult(bool hasLineOfSight)
{
_losResult = hasLineOfSight;
}
// BehaviorTree 引用(#if GRAPH_DESIGNER 保护,避免空引用)
#if GRAPH_DESIGNER
@@ -831,9 +819,9 @@ namespace BaseGames.Enemies
Gizmos.color = new Color(1f, 0.9f, 0.2f, 0.85f);
Gizmos.DrawWireSphere(eyeWorld, 0.07f);
if (inRange || _losResult)
if (inRange || HasLineOfSight)
{
Gizmos.color = _losResult
Gizmos.color = HasLineOfSight
? new Color(1f, 0.5f, 0f, 0.85f)
: new Color(0.6f, 0.6f, 0.6f, 0.25f);
Gizmos.DrawLine(eyeWorld, playerPos);