using System.Collections;
using UnityEngine;
namespace RR.Game2D.Entities.Platforms
{
public class VanishingPlatform : MonoBehaviour
{
[Header("Настройки исчезновения платформы")]
[SerializeField] private float vanishDuration = 0.5f;
[SerializeField] private float reappearDelay = 2f;
[SerializeField] private float reappearDuration = 0.5f;
[SerializeField, Min(0f)] private float vanishStartDelay = 1f;
private CompositeCollider2D _compositeCollider;
private Rigidbody2D _rigidbody;
private SpriteRenderer[] _spriteRenderers;
private Coroutine _vanishCoroutine;
private Coroutine _reappearCoroutine;
private Coroutine _delayedVanishCoroutine;
private Color[] _initialColors;
///
/// Кэширует необходимые компоненты и предупреждает, если чего-то не хватает.
///
private void Awake()
{
_compositeCollider = GetComponent();
_rigidbody = GetComponent();
_spriteRenderers = GetComponentsInChildren();
if (_compositeCollider == null)
Debug.LogWarning($"[{nameof(VanishingPlatform)}] CompositeCollider2D не найден на {gameObject.name}.");
if (_rigidbody == null)
Debug.LogWarning($"[{nameof(VanishingPlatform)}] Rigidbody2D не найден на {gameObject.name}. CompositeCollider2D требует Rigidbody2D.");
if (_spriteRenderers == null || _spriteRenderers.Length == 0)
Debug.LogWarning($"[{nameof(VanishingPlatform)}] SpriteRenderer'ы не найдены на {gameObject.name} и его дочерних объектах.");
}
///
/// Запускает отсрочку исчезновения при входе игрока на платформу.
///
/// Коллизия, по которой определяем игрока.
private void OnCollisionEnter2D(Collision2D other)
{
if (!other.gameObject.CompareTag("Player")) return;
if (_delayedVanishCoroutine != null)
{
StopCoroutine(_delayedVanishCoroutine);
_delayedVanishCoroutine = null;
}
// Если в процессе была корутина Reappear — её отменяем
if (_reappearCoroutine != null)
{
StopCoroutine(_reappearCoroutine);
_reappearCoroutine = null;
}
if (_vanishCoroutine != null)
StopCoroutine(_vanishCoroutine);
// _vanishCoroutine = StartCoroutine(Vanish());
_delayedVanishCoroutine = StartCoroutine(StartVanishWithDelay());
}
///
/// Останавливает исчезновение и инициирует процесс появления, когда игрок уходит.
///
/// Коллизия выхода игрока.
private void OnCollisionExit2D(Collision2D other)
{
if (!other.gameObject.CompareTag("Player")) return;
if (_delayedVanishCoroutine != null)
{
StopCoroutine(_delayedVanishCoroutine);
_delayedVanishCoroutine = null;
}
// Если в процессе была корутина Vanish — её отменяем
if (_vanishCoroutine != null)
{
StopCoroutine(_vanishCoroutine);
_vanishCoroutine = null;
}
if (_reappearCoroutine != null)
StopCoroutine(_reappearCoroutine);
_reappearCoroutine = StartCoroutine(Reappear());
}
///
/// Плавно уменьшает альфу спрайтов до нуля и отключает физику платформы.
///
private IEnumerator Vanish()
{
if (_spriteRenderers == null || _spriteRenderers.Length == 0)
yield break; // нечего анимировать
// Сохраняем начальные цвета для всех рендереров (если ещё не сохранены)
if (_initialColors == null || _initialColors.Length != _spriteRenderers.Length)
{
_initialColors = new Color[_spriteRenderers.Length];
for (int i = 0; i < _spriteRenderers.Length; i++)
_initialColors[i] = _spriteRenderers[i].color;
}
// Запоминаем текущую альфу для каждого рендерера
float[] startAlphas = new float[_spriteRenderers.Length];
for (int i = 0; i < _spriteRenderers.Length; i++)
startAlphas[i] = _spriteRenderers[i].color.a;
float elapsed = 0f;
while (elapsed < vanishDuration)
{
elapsed += Time.deltaTime;
float t = vanishDuration > 0f ? Mathf.Clamp01(elapsed / vanishDuration) : 1f;
for (int i = 0; i < _spriteRenderers.Length; i++)
{
Color c = _initialColors[i];
float alpha = Mathf.Lerp(startAlphas[i], 0f, t);
_spriteRenderers[i].color = new Color(c.r, c.g, c.b, alpha);
}
yield return null;
}
// Принудительно установить 0 альфу
for (int i = 0; i < _spriteRenderers.Length; i++)
{
Color c = _initialColors[i];
_spriteRenderers[i].color = new Color(c.r, c.g, c.b, 0f);
}
if (_rigidbody)
_rigidbody.simulated = false; // отключаем Collider через Rigidbody2D
_vanishCoroutine = null;
}
///
/// Плавно возвращает платформу и повторно включает физику после задержки.
///
private IEnumerator Reappear()
{
if (_spriteRenderers == null || _spriteRenderers.Length == 0)
yield break; // нечего анимировать
// Убедимся, что у нас есть базовые цвета — если нет, прочитаем текущие
if (_initialColors == null || _initialColors.Length != _spriteRenderers.Length)
{
_initialColors = new Color[_spriteRenderers.Length];
for (int i = 0; i < _spriteRenderers.Length; i++)
_initialColors[i] = _spriteRenderers[i].color;
}
// Задержка перед появлением (как в предыдущей логике)
yield return new WaitForSeconds(reappearDelay);
// Запоминаем текущую альфу для каждого рендерера
float[] startAlphas = new float[_spriteRenderers.Length];
for (int i = 0; i < _spriteRenderers.Length; i++)
startAlphas[i] = _spriteRenderers[i].color.a;
float elapsed = 0f;
while (elapsed < reappearDuration)
{
elapsed += Time.deltaTime;
float t = reappearDuration > 0f ? Mathf.Clamp01(elapsed / reappearDuration) : 1f;
for (int i = 0; i < _spriteRenderers.Length; i++)
{
Color c = _initialColors[i];
float alpha = Mathf.Lerp(startAlphas[i], 1f, t);
_spriteRenderers[i].color = new Color(c.r, c.g, c.b, alpha);
}
yield return null;
}
// Принудительно установить полную непрозрачность
for (int i = 0; i < _spriteRenderers.Length; i++)
{
Color c = _initialColors[i];
_spriteRenderers[i].color = new Color(c.r, c.g, c.b, 1f);
}
if (_rigidbody)
_rigidbody.simulated = true; // возвращаем физику
_reappearCoroutine = null;
}
///
/// Позволяет внешним системам сразу запустить исчезновение (без ожидания).
///
public void TriggerVanish()
{
if (_delayedVanishCoroutine != null)
{
StopCoroutine(_delayedVanishCoroutine);
_delayedVanishCoroutine = null;
}
if (_reappearCoroutine != null)
{
StopCoroutine(_reappearCoroutine);
_reappearCoroutine = null;
}
if (_vanishCoroutine != null)
StopCoroutine(_vanishCoroutine);
_vanishCoroutine = StartCoroutine(Vanish());
}
///
/// Позволяет внешним системам сразу запустить появление.
///
public void TriggerReappear()
{
if (_delayedVanishCoroutine != null)
{
StopCoroutine(_delayedVanishCoroutine);
_delayedVanishCoroutine = null;
}
if (_vanishCoroutine != null)
{
StopCoroutine(_vanishCoroutine);
_vanishCoroutine = null;
}
if (_reappearCoroutine != null)
StopCoroutine(_reappearCoroutine);
_reappearCoroutine = StartCoroutine(Reappear());
}
///
/// Ожидает заданную задержку перед фактическим запуском корутины Vanish.
///
private IEnumerator StartVanishWithDelay()
{
if (vanishStartDelay > 0f)
yield return new WaitForSeconds(vanishStartDelay); // выдерживаем таймер ожидания
_vanishCoroutine = StartCoroutine(Vanish());
_delayedVanishCoroutine = null;
}
}
}