Загрузка данных


using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class FloatingBuildingUI : MonoBehaviour
{
    [Header("Offset")]
    public Vector3 worldOffset = new Vector3(0f, 3f, 0f);

    [Header("Size")]
    public Vector2 canvasSize = new Vector2(120f, 24f);

    private BuildingInstance _building;

    private Canvas _canvas;
    private Image _fill;
    private TextMeshProUGUI _label;

    private Camera _cam;

    void Start()
    {
        _building = GetComponent<BuildingInstance>();

        if (_building == null)
        {
            Destroy(this);
            return;
        }

        CreateUI();

        _building.OnHealthChanged += Refresh;
        _building.OnDied += HandleDeath;

        Refresh(_building.CurrentHealth, _building.MaxHealth);
    }

    void CreateUI()
    {
        GameObject canvasGO = new GameObject("BuildingUI");

        canvasGO.transform.SetParent(transform);

        canvasGO.transform.localPosition = worldOffset;
        canvasGO.transform.localRotation = Quaternion.identity;

        _canvas = canvasGO.AddComponent<Canvas>();

        _canvas.renderMode = RenderMode.WorldSpace;
        _canvas.worldCamera = Camera.main;

        CanvasScaler scaler = canvasGO.AddComponent<CanvasScaler>();
        scaler.dynamicPixelsPerUnit = 20;

        RectTransform canvasRT = canvasGO.GetComponent<RectTransform>();

        canvasRT.sizeDelta = canvasSize;

        canvasGO.transform.localScale = Vector3.one * 0.01f;

        //---------------------------------------------------
        // BG
        //---------------------------------------------------

        GameObject bgGO = new GameObject("BG");

        bgGO.transform.SetParent(canvasGO.transform, false);

        Image bg = bgGO.AddComponent<Image>();

        bg.color = new Color(0, 0, 0, 0.75f);

        RectTransform bgRT = bg.GetComponent<RectTransform>();

        bgRT.anchorMin = Vector2.zero;
        bgRT.anchorMax = Vector2.one;
        bgRT.offsetMin = Vector2.zero;
        bgRT.offsetMax = Vector2.zero;

        //---------------------------------------------------
        // Fill
        //---------------------------------------------------

        GameObject fillGO = new GameObject("Fill");

        fillGO.transform.SetParent(bgGO.transform, false);

        _fill = fillGO.AddComponent<Image>();

        _fill.color = Color.green;
        _fill.type = Image.Type.Filled;
        _fill.fillMethod = Image.FillMethod.Horizontal;
        _fill.fillOrigin = 0;

        RectTransform fillRT = _fill.GetComponent<RectTransform>();

        fillRT.anchorMin = Vector2.zero;
        fillRT.anchorMax = Vector2.one;

        fillRT.offsetMin = new Vector2(2, 2);
        fillRT.offsetMax = new Vector2(-2, -2);

        //---------------------------------------------------
        // TEXT
        //---------------------------------------------------

        GameObject textGO = new GameObject("Text");

        textGO.transform.SetParent(canvasGO.transform, false);

        _label = textGO.AddComponent<TextMeshProUGUI>();

        _label.fontSize = 14;
        _label.alignment = TextAlignmentOptions.Center;
        _label.color = Color.white;

        RectTransform textRT = _label.GetComponent<RectTransform>();

        textRT.anchorMin = Vector2.zero;
        textRT.anchorMax = Vector2.one;

        textRT.offsetMin = Vector2.zero;
        textRT.offsetMax = Vector2.zero;
    }

    void Refresh(int current, int max)
    {
        if (_fill == null)
            return;

        float hp = max > 0 ? (float)current / max : 0f;

        _fill.fillAmount = hp;

        if (hp > 0.6f)
            _fill.color = Color.green;
        else if (hp > 0.3f)
            _fill.color = Color.yellow;
        else
            _fill.color = Color.red;

        if (_label != null)
            _label.text = $"{current} / {max}";
    }

    void HandleDeath()
    {
        if (_canvas != null)
            Destroy(_canvas.gameObject);
    }

    void LateUpdate()
    {
        if (_canvas == null)
            return;

        if (_cam == null)
            _cam = Camera.main;

        if (_cam == null)
            return;

        _canvas.transform.forward =
            _canvas.transform.position - _cam.transform.position;
    }

    void OnDestroy()
    {
        if (_building != null)
        {
            _building.OnHealthChanged -= Refresh;
            _building.OnDied -= HandleDeath;
        }
    }
}