2025-09-24 11:24:38 +05:00

185 lines
4.1 KiB
C#

using DG.Tweening;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace TPSBR.UI
{
public class UIHealth : UIBehaviour
{
// PRIVATE MEMBERS
[SerializeField]
private TextMeshProUGUI _healthText;
[SerializeField]
private Image _healthProgress;
[SerializeField]
private TextMeshProUGUI _maxHealthText;
[SerializeField]
private Image _healthIcon;
[SerializeField]
private Image _healthIcon2;
[SerializeField]
private float _healthAnimationDuration = 0.2f;
[SerializeField]
private Color[] _healthColors;
[SerializeField]
private Animation _criticalAnimation;
[SerializeField]
private float _criticalThreshold = 0.2f;
[SerializeField]
private Image _shieldIcon;
[SerializeField]
private TextMeshProUGUI _shieldText;
[SerializeField]
private Color _shieldInactiveColor = Color.gray;
[SerializeField]
private Image _shieldProgress;
[SerializeField]
private TextMeshProUGUI _maxShieldText;
private int _lastHealth = -1;
private int _lastMaxHealth = -1;
private int _lastShield = -1;
private int _lastMaxShield = -1;
private Health _health;
private Color _shieldColor;
// PUBLIC METHODS
public void UpdateHealth(Health health)
{
if (_health != health)
{
_health = health;
_lastHealth = -1;
_lastMaxHealth = -1;
_lastShield = -1;
_lastMaxShield = -1;
}
// HEALTH
int currentHealth = Mathf.RoundToInt(health.CurrentHealth);
if (currentHealth == 0 && health.CurrentHealth > 0)
{
// Do not show zero if not necessary
currentHealth = 1;
}
int maxHealth = (int)health.MaxHealth;
if (currentHealth != _lastHealth)
{
DOTween.Kill(_healthProgress);
float progress = currentHealth / health.MaxHealth;
_healthProgress.DOFillAmount(progress, _healthAnimationDuration);
_healthText.text = currentHealth.ToString();
UpdateHealthColor(health);
ShowCriticalAnimation(progress);
_lastHealth = currentHealth;
}
if (maxHealth != _lastMaxHealth)
{
if (_maxHealthText != null)
{
_maxHealthText.text = $"{maxHealth}";
}
_lastMaxHealth = maxHealth;
}
// SHIELD
int currentShield = (int)health.CurrentShield;
int maxShield = (int)health.MaxShield;
if (currentShield != _lastShield)
{
DOTween.Kill(_shieldProgress);
float progress = currentShield / health.MaxShield;
_shieldProgress.DOFillAmount(progress, _healthAnimationDuration);
_shieldText.text = currentShield.ToString();
_shieldText.color = currentShield > 0 ? _shieldColor : _shieldInactiveColor;
_shieldIcon.color = currentShield > 0 ? _shieldColor : _shieldInactiveColor;
UpdateHealthColor(health);
_lastShield = currentShield;
}
if (maxShield != _lastMaxShield)
{
if (_maxShieldText != null)
{
_maxShieldText.text = $"{maxShield}";
}
_lastMaxShield = maxShield;
}
}
// MONOBEHAVIOUR
protected void Awake()
{
_shieldColor = _shieldIcon.color;
}
protected void OnEnable()
{
_criticalAnimation.SampleStart();
}
// PRIVATE MEMBERS
private void UpdateHealthColor(Health health)
{
var healthColor = GetHealthColor(health.CurrentHealth / health.MaxHealth);
_healthText.color = healthColor;
_healthIcon.color = healthColor;
_healthIcon2.color = healthColor;
_healthProgress.color = healthColor;
}
private Color GetHealthColor(float healthProgress)
{
float preciseIndex = MathUtility.Map(0f, 1f, 0f, _healthColors.Length - 1, healthProgress);
int fromIndex = (int)preciseIndex;
int toIndex = Mathf.Clamp(fromIndex + 1, 0, _healthColors.Length - 1);
return Color.Lerp(_healthColors[fromIndex], _healthColors[toIndex], preciseIndex - fromIndex);
}
private void ShowCriticalAnimation(float healthProgress)
{
if (healthProgress > _criticalThreshold)
{
if (_criticalAnimation.isPlaying == true)
{
_criticalAnimation.SampleStart();
}
return;
}
if (_criticalAnimation.isPlaying == false)
{
_criticalAnimation.Play();
}
}
}
}