Kursach_StealthAction/Assets/Scripts/BossHealthBarUI.cs
2026-10-23 15:44:09 +03:00

193 lines
7.3 KiB
C#
Raw Permalink 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 UnityEngine;
using UnityEngine.UI;
/// <summary>
/// Шкала здоровья Босса вверху посередине экрана.
/// Показывает имя босса, текущее/максимальное здоровье и плавное заполнение полосы.
/// </summary>
public class BossHealthBarUI : MonoBehaviour
{
private static BossHealthBarUI _instance;
public static BossHealthBarUI Instance
{
get
{
if (_instance == null)
_instance = FindAnyObjectByType<BossHealthBarUI>(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<Font>("LegacyRuntime.ttf");
// 1. Корневой объект
GameObject root = new GameObject("BossHealthBarPanel", typeof(RectTransform), typeof(CanvasGroup));
root.transform.SetParent(hudCanvas, false);
RectTransform rootRt = root.GetComponent<RectTransform>();
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<Image>();
bgImg.color = new Color(0.04f, 0.04f, 0.05f, 0.92f);
Outline outline = root.AddComponent<Outline>();
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<RectTransform>();
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<Text>();
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<RectTransform>();
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<Image>();
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<RectTransform>();
fillRt.anchorMin = Vector2.zero;
fillRt.anchorMax = Vector2.one;
fillRt.sizeDelta = Vector2.zero;
Image fillImg = fillObj.GetComponent<Image>();
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<RectTransform>();
hpTxtRt.anchorMin = Vector2.zero;
hpTxtRt.anchorMax = Vector2.one;
hpTxtRt.sizeDelta = Vector2.zero;
Text hpTxt = hpTxtObj.GetComponent<Text>();
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<BossHealthBarUI>();
barUI.rootPanel = root;
barUI.bossTitleText = titleText;
barUI.fillBar = fillImg;
barUI.healthValueText = hpTxt;
barUI.canvasGroup = root.GetComponent<CanvasGroup>();
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<CanvasGroup>();
}
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);
}
}
}