using System.Collections.Generic;
using UnityEngine;
namespace DanroJump.Gameplay
{
///
/// Runtime-контроллер платформы: хранит точки спавна контента и рассылает lifecycle-события.
///
public sealed class PlatformController : MonoBehaviour, IPlatformRuntime, IPlatformLifecycle
{
[SerializeField] private List collectibleSpawnPoints = new();
[SerializeField] private List equipmentSpawnPoints = new();
[SerializeField] private List enemySpawnPoints = new();
///
/// Transform платформы для систем генерации и контента.
///
public Transform Transform => transform;
///
/// Точки, где на платформе можно размещать collectible-предметы.
///
public IReadOnlyList CollectibleSpawnPoints => collectibleSpawnPoints;
///
/// Точки, где на платформе можно размещать специальное оборудование.
///
public IReadOnlyList EquipmentSpawnPoints => equipmentSpawnPoints;
///
/// Точки, где на платформе можно размещать противников.
///
public IReadOnlyList EnemySpawnPoints => enemySpawnPoints;
///
/// Порядковый номер спавна платформы в текущей генерации.
///
public int SpawnIndex { get; private set; }
///
/// Показывает, является ли платформа стартовой.
///
public bool IsStartPlatform { get; private set; }
///
/// Y-координата платформы в момент последней генерации или recycle.
///
public float WorldY { get; private set; }
///
/// Собирает точки спавна при загрузке платформы.
///
private void Awake()
{
CollectSpawnPoints();
}
///
/// Обновляет списки точек спавна при изменениях prefab в редакторе.
///
private void OnValidate()
{
CollectSpawnPoints();
}
///
/// Инициализирует платформу после первого создания.
///
public void Initialize(PlatformSpawnContext context)
{
ApplyContext(context);
NotifyChildrenInitialize(context);
}
///
/// Переиспользует платформу с новым контекстом генерации.
///
public void Recycle(PlatformSpawnContext context)
{
ApplyContext(context);
NotifyChildrenRecycle(context);
}
///
/// Сбрасывает дочерние lifecycle-компоненты платформы.
///
public void ResetPlatform()
{
NotifyChildrenReset();
}
///
/// Запоминает данные текущего спавна платформы.
///
private void ApplyContext(PlatformSpawnContext context)
{
SpawnIndex = context.SpawnIndex;
IsStartPlatform = context.IsStartPlatform;
WorldY = context.WorldY;
}
///
/// Собирает дочерние PlatformSpawnPoint по категориям контента.
///
private void CollectSpawnPoints()
{
collectibleSpawnPoints.Clear();
equipmentSpawnPoints.Clear();
enemySpawnPoints.Clear();
GetComponentsInChildren(true, collectibleBuffer);
foreach (var spawnPoint in collectibleBuffer)
{
if (spawnPoint == null)
{
continue;
}
GetSpawnPointList(spawnPoint.Kind).Add(spawnPoint);
}
collectibleBuffer.Clear();
}
///
/// Возвращает список точек спавна нужной категории.
///
private List GetSpawnPointList(PlatformContentKind kind)
{
switch (kind)
{
case PlatformContentKind.Collectible:
return collectibleSpawnPoints;
case PlatformContentKind.Equipment:
return equipmentSpawnPoints;
case PlatformContentKind.Enemy:
return enemySpawnPoints;
default:
return collectibleSpawnPoints;
}
}
///
/// Сообщает дочерним компонентам о первом создании платформы.
///
private void NotifyChildrenInitialize(PlatformSpawnContext context)
{
GetComponentsInChildren(true, lifecycleBuffer);
foreach (var behaviour in lifecycleBuffer)
{
if (behaviour is IPlatformLifecycle lifecycle && !ReferenceEquals(lifecycle, this))
{
lifecycle.Initialize(context);
}
}
lifecycleBuffer.Clear();
}
///
/// Сообщает дочерним компонентам о рецикле платформы.
///
private void NotifyChildrenRecycle(PlatformSpawnContext context)
{
GetComponentsInChildren(true, lifecycleBuffer);
foreach (var behaviour in lifecycleBuffer)
{
if (behaviour is IPlatformLifecycle lifecycle && !ReferenceEquals(lifecycle, this))
{
lifecycle.Recycle(context);
}
}
lifecycleBuffer.Clear();
}
///
/// Сообщает дочерним компонентам о сбросе платформы.
///
private void NotifyChildrenReset()
{
GetComponentsInChildren(true, lifecycleBuffer);
foreach (var behaviour in lifecycleBuffer)
{
if (behaviour is IPlatformLifecycle lifecycle && !ReferenceEquals(lifecycle, this))
{
lifecycle.ResetPlatform();
}
}
lifecycleBuffer.Clear();
}
private readonly List collectibleBuffer = new();
private readonly List lifecycleBuffer = new();
}
}