sea-battle-vr/Assets/Scripts/Gameplay/Core/UI/HealthSegmentedView.cs

114 lines
4.3 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.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
using System.Threading;
public class HealthSegmentedView : MonoBehaviour
{
[SerializeField] private List<GameObject> segments;
[Header("Blink Settings")]
[SerializeField] private float blinkInterval = 0.1f; // Интервал между миганиями
[SerializeField] private int blinkCount = 3; // Количество миганий
private Health playerHealth;
private int lastDamagedCount = -1; // Количество поврежденных сегментов
private CancellationTokenSource cancellationTokenSource;
public void Initialize()
{
playerHealth = G.PlayerStateModel.PlayerHealthComponent;
playerHealth.HealthChanged += Refresh;
Refresh(-1);
}
void Refresh(float healthChanged)
{
int newDamagedCount = CalculateDamagedSegmentsCount();
// Если количество поврежденных сегментов увеличилось (получили урон)
if (newDamagedCount > lastDamagedCount && lastDamagedCount != -1)
{
int newlyDamagedCount = newDamagedCount - lastDamagedCount;
// Новые поврежденные сегменты - это те, что находятся в диапазоне [lastDamagedCount, newDamagedCount)
BlinkNewlyDamagedSegments(lastDamagedCount, newlyDamagedCount).Forget();
}
// Обновляем отображение
for (int i = 0; i < segments.Count; i++)
{
bool shouldBeActive = i < newDamagedCount; // Активны = повреждены (показывают урон)
segments[i].SetActive(shouldBeActive);
}
lastDamagedCount = newDamagedCount;
}
private int CalculateDamagedSegmentsCount()
{
return (int)((float)segments.Count * (1 - playerHealth.HpPercent));
}
private async UniTaskVoid BlinkNewlyDamagedSegments(int startIndex, int count)
{
// Отменяем предыдущее мигание
cancellationTokenSource?.Cancel();
cancellationTokenSource = new CancellationTokenSource();
var token = cancellationTokenSource.Token;
// Получаем новые поврежденные сегменты
List<GameObject> newDamagedSegments = new List<GameObject>();
for (int i = startIndex; i < startIndex + count && i < segments.Count; i++)
{
newDamagedSegments.Add(segments[i]);
}
// Они уже должны быть активны (повреждены), но мы будем мигать для визуального эффекта
// Мигаем указанное количество раз
for (int i = 0; i < blinkCount; i++)
{
if (token.IsCancellationRequested)
break;
// Выключаем сегменты (как будто они восстанавливаются)
foreach (var segment in newDamagedSegments)
{
if (segment != null)
segment.SetActive(false);
}
await UniTask.Delay((int)(blinkInterval * 1000), cancellationToken: token);
if (token.IsCancellationRequested)
break;
// Включаем обратно (показываем повреждение)
foreach (var segment in newDamagedSegments)
{
if (segment != null)
segment.SetActive(true);
}
await UniTask.Delay((int)(blinkInterval * 1000), cancellationToken: token);
}
// В конце мигания УБЕЖДАЕМСЯ, что сегменты включены (повреждены)
if (!token.IsCancellationRequested)
{
foreach (var segment in newDamagedSegments)
{
if (segment != null)
segment.SetActive(true); // Оставляем включенными - они показывают полученный урон
}
}
}
private void OnDestroy()
{
cancellationTokenSource?.Cancel();
cancellationTokenSource?.Dispose();
if (playerHealth != null)
playerHealth.HealthChanged -= Refresh;
}
}