Is there a practical way to access a button text, without calling GetComponet every frame and without writing long lines of code? (the if else lines).
void ButtonUI()
{
foreach (var item in UIbuttons)
{
if (item.gameObject == EventSystem.current.currentSelectedGameObject)
{
item.GetComponentInChildren<TextMeshProUGUI>().color = SelectedColor;
}
else
{
item.GetComponentInChildren<TextMeshProUGUI>().color = Color.black;
}
}
//if (EventSystem.current.currentSelectedGameObject == ButtonContinueGame.gameObject)
//{
// TextContinueGame.color = SelectedColor;
//}
//else
//{
// TextContinueGame.color = Color.black;
//}
//if (EventSystem.current.currentSelectedGameObject == ButtonNewGame.gameObject)
//{
// TextNewGame.color = SelectedColor;
//}
//else
//{
// TextNewGame.color = Color.black;
//}
//if (EventSystem.current.currentSelectedGameObject == ButtonSettings.gameObject)
//{
// TextSettings.color = SelectedColor;
//}
//else
//{
// TextSettings.color = Color.black;
//}
//if (EventSystem.current.currentSelectedGameObject == ButtonQuit.gameObject)
//{
// TextQuit.color = SelectedColor;
//}
//else
//{
// TextQuit.color = Color.black;
//}
}
What type is “item”?
You could store your “UIbuttons” as TMPUGUI-objects.
Or create a custom class on that object that holds references to its sub-objects. Then use that.
The var “item” is a Button.
I’ve had problems with using custom classes as a list. Progress becomes lost/glitches when editing, sometimes multiple weird errors that I can’t figure out with google, double-clicking, reading the error message or asking the forum.
Well fix that first. That’s on you. Figure out what you’re doing wrong. The entire concept of collections of classes is a fundamental point of doing operations on a computer.
Generally speaking, when in Unity, act like a Unity user: drag references to things into predefined slots on your custom object. This avoids all the overhead and confusion of doing GetComponent():
- specifying the wrong class type
- looking in the wrong place (on the wrong GameObject)
- getting the wrong one back
Yes you can use GetComponent() but think of it more as a super ultra ninja blackbelt command that you only use when there isn’t a better way to do things and you absolutely know exactly what you’re doing and where you’re looking.
If you want an example of dynamically populating a UI in a Unity Way™, with predefined “things” that represent pieces of similar data (such as for an inventory or list of choices), you’re welcome to study the attached example. It uses a single exemplar object with functions provided to fill out the interesting parts, and it dynamically makes as many as are needed to display the sprites that it finds.
8723331–1179720–DynamicUIDemo.unitypackage (96.1 KB)
I’ve already replaced my lists/arrays with local variables/a single custom list to edit in the inspector/hard coded. For example, the foreach Buttons in the first post.
private void Start()
{
UIbuttons = new Button[] { ButtonContinueGame, ButtonNewGame, ButtonSettings, ButtonQuit};
}
Those 3 ways are sometimes a bit slower then setting up multiple lists/arrays to edit in the inspector. but the end result is the same and I’ve had no issues. The UnityPackage provided has more or less the same workflow I’m doing.
While GetComponent in the first post has no noticeable performance difference. I still don’t like seeing it be used every frame and would like to edit it if there is a practical alternative that doesn’t take up a lot of lines of code.
Your options are:
- Serialize references to the components in a collection
- Get/cache references to the components in Awake/Start
- GetComponent the components when you need them
That’s in order of my preference.
That said, if you don’t have a performance issue, don’t worry about it too much.
1 Like
I’ve managed to stop GetComponent from being called every frame.
public class UIButtons
{
public Button button;
public TextMeshProUGUI text;
public UIButtons(Button button, TextMeshProUGUI text)
{
this.button = button;
this.text = text;
}
}
private void Start()
{
MenuButtons = new List<UIButtons>();
Button[] buttonlist = new Button[] { ButtonContinueGame, ButtonNewGame, ButtonSettings, ButtonQuit };
foreach (Button item in buttonlist)
{
MenuButtons.Add(new UIButtons(item, item.GetComponentInChildren<TextMeshProUGUI>()));
}
}
void ButtonUI()
{
foreach (var item in MenuButtons)
{
if (item.button.gameObject == EventSystem.current.currentSelectedGameObject)
{
item.text.color = SelectedColor;
}
else
{
item.text.color = Color.black;
}
}
}