Danro/Assets/Scripts/Entities/Props/Platforms/VanishingPlatform.cs

259 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
/// Кэширует необходимые компоненты и предупреждает, если чего-то не хватает.
/// </summary>
private void Awake()
{
_compositeCollider = GetComponent<CompositeCollider2D>();
_rigidbody = GetComponent<Rigidbody2D>();
_spriteRenderers = GetComponentsInChildren<SpriteRenderer>();
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} и его дочерних объектах.");
}
/// <summary>
/// Запускает отсрочку исчезновения при входе игрока на платформу.
/// </summary>
/// <param name="other">Коллизия, по которой определяем игрока.</param>
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());
}
/// <summary>
/// Останавливает исчезновение и инициирует процесс появления, когда игрок уходит.
/// </summary>
/// <param name="other">Коллизия выхода игрока.</param>
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());
}
/// <summary>
/// Плавно уменьшает альфу спрайтов до нуля и отключает физику платформы.
/// </summary>
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;
}
/// <summary>
/// Плавно возвращает платформу и повторно включает физику после задержки.
/// </summary>
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;
}
/// <summary>
/// Позволяет внешним системам сразу запустить исчезновение (без ожидания).
/// </summary>
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());
}
/// <summary>
/// Позволяет внешним системам сразу запустить появление.
/// </summary>
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());
}
/// <summary>
/// Ожидает заданную задержку перед фактическим запуском корутины Vanish.
/// </summary>
private IEnumerator StartVanishWithDelay()
{
if (vanishStartDelay > 0f)
yield return new WaitForSeconds(vanishStartDelay); // выдерживаем таймер ожидания
_vanishCoroutine = StartCoroutine(Vanish());
_delayedVanishCoroutine = null;
}
}
}