using System.Collections.Generic; using UnityEngine; namespace DanroJump.Gameplay { /// /// Один prefab-вариант с весом для случайного выбора. /// [System.Serializable] public sealed class WeightedPrefabOption { [SerializeField] private GameObject prefab; [SerializeField] [Min(0f)] private float weight = 1f; /// /// Prefab, который может быть выбран генератором. /// public GameObject Prefab => prefab; /// /// Относительный вес prefab в случайном выборе. /// public float Weight => weight; /// /// Выбирает prefab из списка пропорционально весам. /// /// True, если найден валидный prefab с положительным весом. public static bool TrySelect(IReadOnlyList options, System.Random random, out GameObject prefab) { return TrySelect(options, random, null, out prefab); } /// /// Выбирает prefab среди вариантов, которые проходят дополнительный фильтр. /// public static bool TrySelect( IReadOnlyList options, System.Random random, System.Predicate prefabFilter, out GameObject prefab) { prefab = null; var totalWeight = 0f; if (options == null) { return false; } foreach (var option in options) { if (IsSelectable(option, prefabFilter)) { totalWeight += option.Weight; } } if (totalWeight <= 0f) { return false; } var roll = (float)((random != null ? random.NextDouble() : 0d) * totalWeight); foreach (var option in options) { if (!IsSelectable(option, prefabFilter)) { continue; } roll -= option.Weight; if (roll <= 0f) { prefab = option.Prefab; return true; } } return false; } private static bool IsSelectable(WeightedPrefabOption option, System.Predicate prefabFilter) { return option?.Prefab != null && option.Weight > 0f && (prefabFilter == null || prefabFilter(option.Prefab)); } } }