Not sure if the docs are lacking or if there is something missing here, but I can’t see how you can refer to a specific UI element, as child of another, with getcomponent(); if you have more than one.
Example: a panel with 3 buttons, or with 3 text elements, or with 3 checkbox: you cannot access directly each of them, just using GetComponent(), since you will get the first element only in this way.
I did not find a way to call GetComponent using the name of the component itself; you can specify the type (GetComponent or GetComponent), but if there is more than one type on that object, you have no control on which one will be returned to you.
Is this a limitation of the existing API, which didn’t account for the possibility that a gameobject may have more than one component of the same type? (which is true for anything beside UI elements, from what I remember…you can’t put 2 times the same component or script, so make sense that all that you need to pass is the type of the component).
Or there is some other way to use GetComponent, addressing a specific UI component ? Beside using GameObject.Find(), or hardcode in the editor the elements one by one, I can’t see how it would be possible, to be honest.
Works if you call it in the Awake or Start method, but while in the loop, that would cause a big performance hit (at least that’s what the manual says).
Yep, that seems to be the most used method, looking at the various tutorials.
My concern is just that using too much the editor, resctrict the options that you may have at runtime. Can’t beat a public field in the inspector + drag-and-drop of the object directly on the script.
Yes. I have a lot of gui elements created and used only during runtime myself, and I usually save a reference to them, in an array, dictionary or list depending on the situation. If you post example code or explain your issue in detail I might be able to find a different solution for you.
Thanks for the help. I am using already the same methods that you use (as I did mention in the original post); I was hoping that I did miss something on the documentation, which is why I did post here.
Reference via editor is fine; when using a panel that display the same data all the time.
A data structure holding reference to the elements, is a solution when you have few elements; otherwise you end up with a big list; although the issue is mitigated by the low overhead to retrieve the fields to modify.
My case is pretty much a generic UI, where I have multiple fields as children of the same panel, and different buttons.
I can use either method described earlier to set it up, but I was hoping that Unity would supply a way to access components on a UI canvas, in a different way; like a GetComponent passing the name of the component, that will allow to get the reference to it, without using neither Find() nor drag and drop the elements in the editor
GameObject.Find searches the entire scene, it can be slow if there are a large number of objects.
Transform.Find searches the children of the transform its called on. As most transforms only have a handful of children, it’s not particuarly expensive. It is still strong based programming, and is subject to the normal pitfalls of strings.
Another alternative is to use something like GetComponentsInChildren. This will give you a list of all of the components. You can then iterate through the list as you please.
I wish the manual would describe such things…thanks for the insight.
I used to think that they were equivalent, but if the transform.Find is searching only on the children of the object; then it could be a viable candidate for a fast retrieval of a UI element, when you have multiple instances of it.
Sadly that is not different from calling GetComponent; it return you a list of components T.
Once you get the components list, you have to parse them one by one, until you have a match for your element by name.
Now picture a list with N objects…your time complexity for a search in a unsorted list, is equal to the number of elements in it; in the worst case.
So you have the time needed to parse ALL the items in your scene, of component T, which is one loop, and then you have a second loop, where you search the element once you have to retrive one item and use it. This is before you even update that item, this is just to get to that item…ironically this method takes you more time, compared to just use the GameObject.Find.
As you can imagine, it is nowhere near performant and scalable, when N increase
How can you do that in the editor, if 80% of your elements are created at runtime?
I agree that what can be set up in the editor, should be done there; but at least in my case; most of the assets in game are created on demand. I did arrange elements so I have to find just the parent, and then use mostly transform.find; while for assets that are visible when the scene load, I just use the editor.
Creating it at runtime is even easier. You have a direct reference when you create the object. Just save it somewhere relevant. Or set it up at create time and forget about it,