Files
zeling_v2/Assets/_Game/Scripts/Enemies/Perception/SightBatchSystem.cs
Joywayer d27ae9407d 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.
2026-06-02 23:18:20 +08:00

108 lines
5.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.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;
}
}
}