Thought I’d write an update on this in case anyone cares. Before really being able to tackle programatic layouts, I needed to make the creation/skinning/reuse of complex controls easier.
Right now if you want something like a combo box, it’s about 8 objects with a ton of components on them, plus at least one object per item in the list. This is a royal pain to manage. Even a simple button with text is two objects, which means you need to programmatically look up the text component from the button reference, etc.
I’m not a big fan of this. I want my controls to be encapsulated. I like that they can be made of simple components, but I don’t want to HAVE to make them from this mess every time, because it’s extremely error prone and finicky.
So, here’s what I’m doing for my combo box:
Installed in the UI menu is a ComboBox option. It creates a RectTransform with my “StyledComboBox” component on it. This component has two public fields, one for a ComboBoxPrefab and another for a prefab for the items which will populate the combo box. When the component is created (or the prefabs are changed in the editor), the component instantiates the prefab and stretches the prefab to fill the current rect. All the internal objects are hidden from the user - you only see the original ComboBox object you created in the hierarchy window.
The StyledComboBox component acts as a single API for the entire system. I can get/set/add/remove items from it, and it will handle new instances as well as passing the data to the items inside of it. For instance, our combo box’s item prefab might use the StyledImageText component. When it gets instantiated, it’s Populate(object o) function is called on it, and it can see if o is a text, image, or both. So populating the combo box looks like so:
// just text
comboBox.AddItems("Test1", "Test2", "Test3", "Fuck", "I", "Don't", "Believe", "This", "Shit", "Isn't", "Included");
// text + images
comboBox.AddItems(new StyledComboBox.Data("Text", myTexture));
Now, if one of my artists decides they’d like to skin the combo box, or the items inside it, all they have to do is duplicate the prefab and set it up the way they want. Then they can drag the prefab onto any combo box they want to use the new style.
This gives me styling, smaller project files (since none of the controls are stored in the file, rather instantiated on the fly), and I can prefab my panels (since again, it’s not really storing the prefab in the scene - just an object which knows how to instantiate it).
Overall, I’ll likely wrap every control this way - even a button with a label is two objects, and I want one API/Pointer to deal with on every control type. I still haven’t gotten the combo box to work correctly - it currently populates the control and it’s items correctly, but there seem to be numerous masking bugs and such that prevent it from fully working correctly.
Honestly, I really wish I didn’t have to write this kind of stuff - I spend approximately 20% of my time working on my game, and the bulk of the time making Unity robust enough to actually ship a large project with. If prefab’s could a) be nested, and b) hide objects/properties from the user of the prefab (encapsulation!), then none of this would be necessary. Sigh…