So Unity added nested prefabs in their newest (stable) release. All my games are usually very code-centric and I don’t build complex scenes, so I never really cared about nested prefab features as they apply to designers. But now I am doing a lot of UI and I actually see a whole lot of potential for using these. In fact, this whole post can be summed up as me using every new feature from nested prefabs. I started out just by trying out some of the features, but ended up heavily utilizing the new system.

So now every element in every prefab can be a prefab, which means it can share its values across the game even when it’s hidden somewhere deep within prefab hierarchies. To illustrate, the first thing I can do is make a generic background prefabs that has a sprite set up the way I want my generic backgrounds to appear:

They I can just place it anywhere I want, such as in my main menu panel (prefab):

Now it has a generic background and it will update if I ever decide to change it, for example, add some extra prettiness.

And this gets more modular. For example, I am making UI text prefabs that have the fonts and sizes and everything selected and shared between UI parts:

This means I can easily replace my fonts everywhere, make all labels smaller or larger, add font effects like outlines and such.

I can make a button prefab and I can have it contain a background and a caption that are fully based on those prefabs:

So now all buttons will appear consistently and use the correct even more generic elements. I am just so excited about this feature now that I have had the chance to work with it!

And I can use these buttons in places like menus:

Obviously, I can override certain value, like the caption text and make any adjustments I need. But these are purely contextual ones and not structural ones. That is, for example, labels differ for all buttons, but label position stays the same.

There is one particular prefab feature that they preserve the user’s positioning and sizing of the prefab. That is, updates to the prefab won’t resize the children. This is a big problem for elements like buttons, where I decided I want them to be 120 px and then change them to 140 px. None of the UIs would update.

Instead, I added a script to my prefabs, so that when they are used as elements, they correctly set their size back to what they are in the prefab:

This is an editor-only script, so I’m not losing any performance or such.

A similar feature is where I want to quickly swap sprites for an element (like button pressed versus not), but I don’t want custom logic for each such element. Instead, I have a generic sprite swapper script that is part of the prefab and knows what sprite to use:

All I do is call Select()  or Deselect()  on it and it updates as needed. Of course, my control code still has to call it, but that’s up to them. The result is that they can expect consistent results.

Some elements are already complex enough that they can serve as parent elements for additional variants (which is also a new prefab feature) — the variant prefab is like the parent but with extra modifications. These modifications carry over to anyone who uses this. In other words, I can make my 120 px button be 80 px int he variant and all UIs will use the 80 px button:

Anyway, I won’t list every reusable element I have, but so far, here is my list:

Making all of those and testing took quite some time, as is usual for UI work. However, I can now adjust existing panels much quicker as I basically drag & drop elements. Of course, I still need to position and size everything, which is the major timesink. I do have various additional reusable script for UI, notable the element layout (which is now proving invaluable):

It’s similar to Unity’s layout logic, but has some specific things that make it using in simple scenarios much easier.

I already mentioned my tab logic before too, which I have modified. The main parent now better collects and controls the children:

And the children have less options and more common features. They also use the new sprite swapper for full modularity:

There is also a small but very useful script to match sizes between UI elements, so they can auto-size when I change the other:

This is especially useful in tables and such, which have captions that should match sizes with cells.

Anyway, I am adding modular parts as I go through the panels

As a  sidenote, there are three things that the new prefab system somewhat broke. One is that I had the “Make pixel-perfect” button on the canvas, but the new prefab editing logic doesn’t let me do that anymore. So now the button lives on ever canvas renderer, which is basically most of the UI:

I also can no longer easily preview a hierarchy of UI. Like the parent options panel and its child audio settings panel. So it’s hard to see where I am supposed to position things in relation to parents and such. It just adds some extra steps of dragging things around and not forgetting to delete them

And finally, you cannot edit prefabs without opening them. I cannot quickly change a value of two — I have to open the whole prefab in its own “scene”. This makes quickly editing a bunch of prefabs basically impossible. Thankfully, 95% of my configurable stuff is in assets, which are unaffected by any of this.

This whole nested prefab system also means that my quick styling system is by large obsolete. I has a bunch of scripts that used assets with style information that I could drop onto elements and they would automatically adjust themselves. But now all that and more is done with nested prefabs. I will have to remove a few cases where I still use the styling logic and then remove it altogether.

That about wraps it up for modular UI. I will may be revisit this if I gather enough new features, but I am more likely going to mention them with other features. Although, I will cover a bit more about modularity in relation to planned UI navigation in a future post as I’m not happy with my current system.

Related Posts

MicroRogue DevDiary #82 – Modular UI elements
Tagged on:

Leave a Reply

Your email address will not be published. Required fields are marked *