using UnityEngine;
using UnityEngine.UI;
///
/// Шкала здоровья Босса вверху посередине экрана.
/// Показывает имя босса, текущее/максимальное здоровье и плавное заполнение полосы.
///
public class BossHealthBarUI : MonoBehaviour
{
private static BossHealthBarUI _instance;
public static BossHealthBarUI Instance
{
get
{
if (_instance == null)
_instance = FindAnyObjectByType(FindObjectsInactive.Include);
return _instance;
}
}
[Header("Элементы интерфейса")]
public GameObject rootPanel;
public Text bossTitleText;
public Text bossSubText;
public Image fillBar;
public Text healthValueText;
public CanvasGroup canvasGroup;
private float targetFill = 1f;
private float currentFill = 1f;
private bool isVisible = false;
public static BossHealthBarUI Create(Transform hudCanvas)
{
var old = hudCanvas.Find("BossHealthBarPanel");
if (old != null) DestroyImmediate(old.gameObject);
Font defaultFont = Resources.GetBuiltinResource("LegacyRuntime.ttf");
// 1. Корневой объект
GameObject root = new GameObject("BossHealthBarPanel", typeof(RectTransform), typeof(CanvasGroup));
root.transform.SetParent(hudCanvas, false);
RectTransform rootRt = root.GetComponent();
rootRt.anchorMin = new Vector2(0.5f, 1.0f);
rootRt.anchorMax = new Vector2(0.5f, 1.0f);
rootRt.pivot = new Vector2(0.5f, 1.0f);
rootRt.anchoredPosition = new Vector2(0f, -22f);
rootRt.sizeDelta = new Vector2(560f, 62f);
// 2. Фон контейнера
Image bgImg = root.AddComponent();
bgImg.color = new Color(0.04f, 0.04f, 0.05f, 0.92f);
Outline outline = root.AddComponent();
outline.effectColor = new Color(1.0f, 0.25f, 0.25f, 0.65f);
outline.effectDistance = new Vector2(1.5f, -1.5f);
// 3. Заголовок босса
GameObject titleObj = new GameObject("BossTitle", typeof(RectTransform), typeof(CanvasRenderer), typeof(Text));
titleObj.transform.SetParent(root.transform, false);
RectTransform titleRt = titleObj.GetComponent();
titleRt.anchorMin = new Vector2(0f, 0.62f);
titleRt.anchorMax = new Vector2(1f, 1.0f);
titleRt.offsetMin = new Vector2(15f, 0f);
titleRt.offsetMax = new Vector2(-15f, -4f);
Text titleText = titleObj.GetComponent();
titleText.font = defaultFont;
titleText.fontSize = 15;
titleText.fontStyle = FontStyle.Bold;
titleText.alignment = TextAnchor.MiddleCenter;
titleText.color = new Color(1.0f, 0.3f, 0.3f, 1.0f);
titleText.text = "ТИП-0: АЛЬФА-МУТАНТ (ПАТРИАРХ)";
// 4. Фон полосы здоровья
GameObject barBgObj = new GameObject("BarBackground", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
barBgObj.transform.SetParent(root.transform, false);
RectTransform barBgRt = barBgObj.GetComponent();
barBgRt.anchorMin = new Vector2(0f, 0.16f);
barBgRt.anchorMax = new Vector2(1f, 0.54f);
barBgRt.offsetMin = new Vector2(14f, 0f);
barBgRt.offsetMax = new Vector2(-14f, 0f);
Image barBgImg = barBgObj.GetComponent();
barBgImg.color = new Color(0.18f, 0.05f, 0.05f, 0.95f);
// 5. Заполнение полосы (красный градиент)
GameObject fillObj = new GameObject("BarFill", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
fillObj.transform.SetParent(barBgObj.transform, false);
RectTransform fillRt = fillObj.GetComponent();
fillRt.anchorMin = Vector2.zero;
fillRt.anchorMax = Vector2.one;
fillRt.sizeDelta = Vector2.zero;
Image fillImg = fillObj.GetComponent();
fillImg.type = Image.Type.Filled;
fillImg.fillMethod = Image.FillMethod.Horizontal;
fillImg.fillOrigin = (int)Image.OriginHorizontal.Left;
fillImg.color = new Color(0.95f, 0.2f, 0.2f, 1.0f);
// 6. Текст числового значения HP
GameObject hpTxtObj = new GameObject("HealthText", typeof(RectTransform), typeof(CanvasRenderer), typeof(Text));
hpTxtObj.transform.SetParent(barBgObj.transform, false);
RectTransform hpTxtRt = hpTxtObj.GetComponent();
hpTxtRt.anchorMin = Vector2.zero;
hpTxtRt.anchorMax = Vector2.one;
hpTxtRt.sizeDelta = Vector2.zero;
Text hpTxt = hpTxtObj.GetComponent();
hpTxt.font = defaultFont;
hpTxt.fontSize = 13;
hpTxt.fontStyle = FontStyle.Bold;
hpTxt.alignment = TextAnchor.MiddleCenter;
hpTxt.color = Color.white;
hpTxt.text = "500 / 500";
BossHealthBarUI barUI = root.AddComponent();
barUI.rootPanel = root;
barUI.bossTitleText = titleText;
barUI.fillBar = fillImg;
barUI.healthValueText = hpTxt;
barUI.canvasGroup = root.GetComponent();
barUI.canvasGroup.alpha = 0f;
barUI.canvasGroup.blocksRaycasts = false;
barUI.canvasGroup.interactable = false;
root.SetActive(false);
return barUI;
}
private void Awake()
{
_instance = this;
if (canvasGroup == null) canvasGroup = GetComponent();
}
private void Update()
{
// Плавное заполнение полосы
currentFill = Mathf.MoveTowards(currentFill, targetFill, 2.5f * Time.deltaTime);
if (fillBar != null)
{
fillBar.fillAmount = currentFill;
}
// Плавный альфа-фейд
if (canvasGroup != null)
{
float targetAlpha = isVisible ? 1f : 0f;
canvasGroup.alpha = Mathf.MoveTowards(canvasGroup.alpha, targetAlpha, 4f * Time.deltaTime);
if (!isVisible && canvasGroup.alpha <= 0.01f && gameObject.activeSelf)
{
gameObject.SetActive(false);
}
}
}
public void ShowBoss(string name, float current, float max)
{
if (bossTitleText != null) bossTitleText.text = name;
targetFill = Mathf.Clamp01(current / max);
currentFill = targetFill;
if (fillBar != null) fillBar.fillAmount = currentFill;
if (healthValueText != null) healthValueText.text = $"{Mathf.CeilToInt(current)} / {Mathf.CeilToInt(max)}";
gameObject.SetActive(true);
isVisible = true;
}
public void UpdateHealth(float current, float max)
{
targetFill = Mathf.Clamp01(current / max);
if (healthValueText != null) healthValueText.text = $"{Mathf.Max(0, Mathf.CeilToInt(current))} / {Mathf.CeilToInt(max)}";
if (current <= 0f)
{
HideBoss(false);
}
}
public void HideBoss(bool instant = false)
{
isVisible = false;
if (instant)
{
if (canvasGroup != null) canvasGroup.alpha = 0f;
gameObject.SetActive(false);
}
}
}