Подробные изменения: - Добавлены и доработаны модальные окна главного меню, сервисные настройки, шаблоны UI Toolkit и единый scene-flow сервис для переходов между сценами. - Расширена gameplay-архитектура: сессия забега, HUD, спавн контента платформ, collectible-предметы, оборудование, хрупкие и движущиеся платформы. - Добавлена база противников: типы спавна, патрулирование, процедурный спавнер, правила размещения через ScriptableObject-сложности и убийство врагов прыжком сверху. - Исправлены смерть и respawn игрока, финальный GameOver, отскоки от врагов, пружин и boost-предметов, а также проход сквозь врагов при усиленном подъеме. - Проведен рефакторинг взаимодействия систем: общий landing context, единые правила player-contact, NonLazy gameplay session, fail-fast installer и централизованный выбор точек спавна. - Обновлены сцены, prefab-ассеты, difficulty stages, ресурсы главного меню, настройки проекта, roadmap и аппаратная COM-интеграция. - Добавлены ассеты летучей мыши, врагов, collectibles, TextMesh Pro, ProjectContext и gameplay UI. Проверки: - dotnet build .\\Assembly-CSharp.csproj --no-restore - Unity validation ключевых gameplay/UI/scene-flow скриптов - Unity Console после force refresh без ошибок
91 lines
2.9 KiB
C#
91 lines
2.9 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace DanroJump.Gameplay
|
||
{
|
||
/// <summary>
|
||
/// Один prefab-вариант с весом для случайного выбора.
|
||
/// </summary>
|
||
[System.Serializable]
|
||
public sealed class WeightedPrefabOption
|
||
{
|
||
[SerializeField] private GameObject prefab;
|
||
[SerializeField] [Min(0f)] private float weight = 1f;
|
||
|
||
/// <summary>
|
||
/// Prefab, который может быть выбран генератором.
|
||
/// </summary>
|
||
public GameObject Prefab => prefab;
|
||
|
||
/// <summary>
|
||
/// Относительный вес prefab в случайном выборе.
|
||
/// </summary>
|
||
public float Weight => weight;
|
||
|
||
/// <summary>
|
||
/// Выбирает prefab из списка пропорционально весам.
|
||
/// </summary>
|
||
/// <returns>True, если найден валидный prefab с положительным весом.</returns>
|
||
public static bool TrySelect(IReadOnlyList<WeightedPrefabOption> options, System.Random random, out GameObject prefab)
|
||
{
|
||
return TrySelect(options, random, null, out prefab);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выбирает prefab среди вариантов, которые проходят дополнительный фильтр.
|
||
/// </summary>
|
||
public static bool TrySelect(
|
||
IReadOnlyList<WeightedPrefabOption> options,
|
||
System.Random random,
|
||
System.Predicate<GameObject> 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<GameObject> prefabFilter)
|
||
{
|
||
return option?.Prefab != null &&
|
||
option.Weight > 0f &&
|
||
(prefabFilter == null || prefabFilter(option.Prefab));
|
||
}
|
||
}
|
||
}
|