From 67220b4bbd8358e517894ebb8e87e6fff604e606 Mon Sep 17 00:00:00 2001 From: Joywayer Date: Mon, 27 Jul 2026 09:55:59 +0800 Subject: [PATCH] =?UTF-8?q?refactor(enemy):=20=E5=B0=8F=E6=80=AA=E9=80=89?= =?UTF-8?q?=E6=8B=9B=E6=94=B9=E7=94=A8=20WeightedPick=20=E5=85=B1=E4=BA=AB?= =?UTF-8?q?=E5=8E=9F=E8=AF=AD(=E6=9D=83=E9=87=8D=E7=BC=93=E5=86=B2?= =?UTF-8?q?=E5=A4=8D=E7=94=A8,=E9=9B=B6=20GC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Enemies/Abilities/EnemyAttackSelector.cs | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Assets/_Game/Scripts/Enemies/Abilities/EnemyAttackSelector.cs b/Assets/_Game/Scripts/Enemies/Abilities/EnemyAttackSelector.cs index d10ee61c..d69ef58e 100644 --- a/Assets/_Game/Scripts/Enemies/Abilities/EnemyAttackSelector.cs +++ b/Assets/_Game/Scripts/Enemies/Abilities/EnemyAttackSelector.cs @@ -10,9 +10,14 @@ namespace BaseGames.Enemies.Abilities public sealed class EnemyAttackSelector { private readonly List _candidates; + // 权重缓冲区(与 _candidates 等长,每次选招复用):避免每次选招 new List 造成 GC + private readonly List _weightBuf; public EnemyAttackSelector(IEnumerable candidates) - => _candidates = new List(candidates); + { + _candidates = new List(candidates); + _weightBuf = new List(_candidates.Count); + } public int Count => _candidates.Count; @@ -47,22 +52,19 @@ namespace BaseGames.Enemies.Abilities private IAttackCandidate SelectByWeight(bool hasLOS, bool grounded) { - float total = 0f; + // 有效权重:不合格候选填 0(由共享原语保证零权重项绝不被选中)。缓冲区复用 → 选招零 GC。 + _weightBuf.Clear(); for (int i = 0; i < _candidates.Count; i++) { var c = _candidates[i]; - if (Eligible(c, hasLOS, grounded)) total += Mathf.Max(0f, c.Weight); + _weightBuf.Add(Eligible(c, hasLOS, grounded) ? Mathf.Max(0f, c.Weight) : 0f); } - if (total <= 0f) return SelectByPriority(hasLOS, grounded); // 权重全 0 → 退化为按 Priority 选(并列取首个) - float roll = Random.value * total; - for (int i = 0; i < _candidates.Count; i++) - { - var c = _candidates[i]; - if (!Eligible(c, hasLOS, grounded)) continue; - roll -= Mathf.Max(0f, c.Weight); - if (roll <= 0f) return c; - } - return null; // 理论不达(浮点边界兜底) + + int idx = BaseGames.Core.WeightedPick.Index(_weightBuf); + if (idx >= 0) return _candidates[idx]; + + // 无正权重(合格候选权重全 0)→ 退化为按 Priority 选(并列取首个) + return SelectByPriority(hasLOS, grounded); } } }