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

@@ -0,0 +1,107 @@
using System.Collections.Generic;
using UnityEngine;
namespace BaseGames.Enemies.Perception
{
/// <summary>
/// 场景级 Sight 槽位批量调度器Phase 3 性能优化)。
///
/// <b>设计意图:</b>
/// Sight 槽位内置多点 LOS 射线检测当场景中存在大量敌人时10+ 个),
/// 每帧同步刷新所有 Sight 槽位会产生明显的 CPU 峰值。
/// 本组件将全局 Sight 更新量限制在 <see cref="maxSystemsPerFrame"/> 个/帧,
/// 通过轮询方式公平分配每帧的 Sight 预算,把瞬时峰值摊平到多帧。
///
/// <b>使用方式:</b>
/// 1. 在场景中添加一个空 GameObject挂载本组件建议放在 Managers 节点下)。
/// 2. 本组件自动在 <c>DefaultExecutionOrder(-50)</c> 执行,比默认 PhysicsPerceptionSystem 早。
/// 3. 当本组件存在时PhysicsPerceptionSystem.FixedUpdate() 会跳过所有 Sight 槽位的更新,
/// 由本组件统一调度(优雅降级:本组件不存在时 Sight 每帧正常更新)。
///
/// <b>性能参考(测试用):</b>
/// • maxSystemsPerFrame = 460fps20 个敌人 → 平均每帧 4 × losRayCount 次射线,
/// 每个敌人 Sight 刷新周期约 5 帧(~83ms适合慢速视线感应。
/// • 增大此值可减少延迟,减小此值可进一步降低每帧开销。
/// </summary>
[AddComponentMenu("BaseGames/Enemies/Sight Batch System")]
[DefaultExecutionOrder(-50)]
public sealed class SightBatchSystem : MonoBehaviour
{
// ── 单例 ──────────────────────────────────────────────────────────────
public static SightBatchSystem Instance { get; private set; }
// ── 配置 ──────────────────────────────────────────────────────────────
[Min(1)]
[Tooltip("每帧最多更新多少个 PhysicsPerceptionSystem 的 Sight 槽位。\n" +
"建议值:场景敌人数 / 5使平均刷新延迟 ≈ 5 帧)。\n" +
"值越大 = 延迟越低但 CPU 峰值越高;值越小反之。")]
[SerializeField] private int maxSystemsPerFrame = 4;
// ── 内部状态 ──────────────────────────────────────────────────────────
private readonly List<PhysicsPerceptionSystem> _registrants =
new List<PhysicsPerceptionSystem>(32);
private int _offset;
// ── 单例生命周期 ──────────────────────────────────────────────────────
private void Awake()
{
if (Instance != null && Instance != this)
{
Debug.LogWarning("[SightBatchSystem] 场景中存在多个 SightBatchSystem将销毁多余实例。", this);
Destroy(gameObject);
return;
}
Instance = this;
}
private void OnDestroy()
{
if (Instance == this) Instance = null;
}
// ── 注册 / 注销 ───────────────────────────────────────────────────────
/// <summary>PhysicsPerceptionSystem.Awake() 自动调用。</summary>
public void Register(PhysicsPerceptionSystem system)
{
if (system == null || _registrants.Contains(system)) return;
_registrants.Add(system);
}
/// <summary>PhysicsPerceptionSystem.OnDestroy() 自动调用。O(1) 交换删除。</summary>
public void Unregister(PhysicsPerceptionSystem system)
{
int idx = _registrants.IndexOf(system);
if (idx < 0) return;
int last = _registrants.Count - 1;
_registrants[idx] = _registrants[last];
_registrants.RemoveAt(last);
// 防止 _offset 越界
if (_offset >= _registrants.Count)
_offset = 0;
}
// ── 调度 ──────────────────────────────────────────────────────────────
private void FixedUpdate()
{
int total = _registrants.Count;
if (total == 0) return;
int budget = Mathf.Min(maxSystemsPerFrame, total);
for (int i = 0; i < budget; i++)
{
int idx = (_offset + i) % total;
_registrants[idx].ExecuteSightSlots();
}
_offset = (_offset + budget) % total;
}
}
}