How to properly update UI when the value this UI is showing is changed ?

At first i put it in Update().
But value only changes when “item” is equipped/taked off, so its seems wasteful.
I tried to change UI value from the sourse of a change and use Canvas.ForceUpdateCanvases(); Doesnt work.
May be some method ?

By the way i did not using methods almost at all in my game. My code is just bunch of IF-statemants and varibales.
Something like this where i create my ““Dynamic UI””

using System;
using System.Collections;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;

public class OnHoverItemDescription : MonoBehaviour
{

    private void OnMouseEnter()
    {
        if (gameObject.GetComponent<IsItem>())
        {
            GameObject obj = new(gameObject.name + "_Parent");

            obj.transform.SetParent(transform, true);


            obj.AddComponent<RectTransform>();
            obj.AddComponent<Canvas>();
            obj.AddComponent<SpriteRenderer>();
            obj.AddComponent<CanvasRenderer>();
            obj.AddComponent<GridLayoutGroup>();

            obj.GetComponent<RectTransform>().sizeDelta = new Vector2(5, 5);
            obj.GetComponent<RectTransform>().localPosition = new Vector3(-1, 0, 0);
            obj.GetComponent<Canvas>().renderMode = RenderMode.WorldSpace;
            obj.GetComponent<Canvas>().worldCamera = Camera.main;
            obj.GetComponent<Canvas>().sortingOrder = 15;
            obj.GetComponent<GridLayoutGroup>().cellSize = new Vector2(4, 1);
            obj.GetComponent<GridLayoutGroup>().constraint = GridLayoutGroup.Constraint.FixedColumnCount;
            obj.GetComponent<GridLayoutGroup>().constraintCount = 1;
            obj.GetComponent<GridLayoutGroup>().spacing = new Vector2(0, -0.5f);

            for (int i = 0; i < gameObject.GetComponent<IsItem>().props.Count; i++)
            {
                if (transform.GetChild(0))
                {
                    _ = new GameObject(i.ToString());
                    GameObject.Find(i.ToString()).transform.SetParent(transform.GetChild(0), true);
                    transform.GetChild(0).GetChild(i).AddComponent<TextMeshProUGUI>();
                    transform.GetChild(0).GetChild(i).GetComponent<TextMeshProUGUI>().text = gameObject.GetComponent<IsItem>().props[i].ToString();
                    transform.GetChild(0).GetChild(i).GetComponent<TextMeshProUGUI>().fontSize = 0.3f;
                }
            }
        }
    }

    private void OnMouseOver()
    {
        if (transform.childCount > 0)
        {
            if (Input.GetMouseButton(0))
            {
                transform.GetChild(0).gameObject.SetActive(false);
            }
            else
            {
                transform.GetChild(0).gameObject.SetActive(true);
            }

            LayerMask mask = LayerMask.GetMask("Wrapper");

            if (Physics2D.Raycast(transform.position, Vector2.left, 5f, mask))
            {
                transform.GetChild(0).localPosition = new Vector3(6, 0, 0);
            }
            else
            {
                transform.GetChild(0).localPosition = new Vector3(-1, 0, 0);
            }
        }
    }
    private void OnMouseExit()
    {
        if (transform.childCount > 0)
        {
            transform.GetChild(0).gameObject.SetActive(false);
            Destroy(transform.GetChild(0).gameObject);
        }
    }
}

Wow… my goodness! You really are wasting a huge resource by not using the editor for stuff like this.

This will make your game EXTREMELY hard to work with over time, until it solidifies into a solid black glass slag pile that you have no idea what is safe to touch.

If you want to do it properly, checkout the attached example of a dynamic UI that can have arbitrary counts of things in a grid, with each having custom data.

9557998–1351300–DynamicUIDemo.unitypackage (94 KB)

1 Like

I will try. Its very hard for me to understand others people code.
And by “dynamic” i mean my definition of it (which is misleading and wrong).
My code simply show pop-up of item properties (which may differ if it is a armor or weapon … etc) . Its working at least lol.

Here is the code: (Not for a pop-up code. Its for my “static” always onscreen UI)
I want remove text.text from Update() but if Health is changed, show updated value

using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.VisualScripting.Antlr3.Runtime.Misc;
using UnityEngine;

public class HealthUI : MonoBehaviour
{
    public PlayerManager playerManager;
    TextMeshProUGUI text;

    public int Health;

 

    private void Start()
    {
        text = GetComponent<TextMeshProUGUI>();
    }

    private void Update()
    {
        Health = playerManager.Health;
        text.text = "Health   " + Health;
    }
}

I want remove it from Update()

I would recommend stepping away from legacy GameObject based UGUI. There’s UI Toolkit, which has a visual UI Builder, and connecting things in code is almost trivial and if you take it one step further you even get bindings that automatically update values to and from the UI.

Question is, why do you want to remove it? Does it work? Is it creating too much overhead? If not, no need to overcomplicate the matter.

But to answer your question, you just need to give some means for the UI to listen to the player. As a basic example the player could have an public event Action<int> OnHealthChanged; delegate that the UI hooks into.

Then you have systems like UI Tookit which has a runtime bindings API on 2023.2 and beyond.

2 Likes