The Problem of Creating UI

I had a project needs to restructure the whole UI this year, in a general way to create UI is to set up each element’s attributes like font size, color… etc.

setup-every-attributes
In a general way, I need to set up every attribute for this text element

In the below picture, I need to change all elements one by one if suddenly the art designer wants to change the font color or something else. I can solve this by making a block to a prefab, then instantiate and modify the text of each instance. By doing so I can change all block style at once by changing the prefab.

Screen Shot 2018-03-25 at 12.40.18
Make a prefab for this kind of block, then I can change all block style by changing styles of the prefab

But what if it obviously needs many different prefabs with the same style settings? Going through all prefabs and modifying the styles is still much time cost.

Screen Shot 2018-03-25 at 12.40.45
Need to manually change all prefabs with the same style settings

ScriptableObject is a good approach for Game Settings

In Unity3D, a powerful class called ScriptableObject, ScriptableObject is like MonoBehavior but it doesn’t attach to GameObject. We can also instantiate ScriptableObject and put them into the game project just like any other assets.

There are already a lot of articles about what ScriptableObject is, so I’m just going to talk about how I use it to manage game UI styles.

Combine the Concepts of CSS and Unity3D

As a former front-end-developer, I like the concept how CSS controls the look and feel of a website: Elements only care about what classes they are, let CSS handles the details.

/// CSS doesn't care about who used it
/// It only descripts how the UI look like
.popup.header {
  background-color: dark;
}

.popup.title_color {
  font-color: white;
}

.large_size {
  font-size: large;
}

/// Elements don't care about the style details
/// They just define what classes they are
<header class="popup header">
  <h1 class="popup title_color large_size">Popup Title</h1>
</header>

From this concept, I created several classes for my UI SKin System:

SkinComponent

A SkinComponent attaches to a GameObject and defines what classes it has.

assign-selectors-to-skin-component

SkinModifier

A SkinModifier is actually an instance of ScriptableObject. It works like a CSS rule-set, has selectors to determine what elements it’s going to apply to, and also defines how it’ll affect those elements.

 

modifier-is-like-css
Notice that I didn’t assign the color code directly. Instead, I created a Black ScriptableObject for the color.

 

In addition, I extracted some values like color and size to other ScriptableObject classes, so that I can change those values like large font size from 30 to 36 at once.

SkinAsset

A SkinAsset contains a set of SkinModifiers, you can imagine it’s a CSS file contains all CSS rules you need.

skin-asset-is-like-css-file

SkinManager

Finally, the SkinManager handles the references of SkinComponent and SkinModifier, it also publishes notifications to SkinComponents when SkinAssets was changed, therefore I can change the whole skin(theme) at runtime.

skin-manager-has-a-skin-asset

Screen Shot 2018-03-25 at 10.48.05Screen Shot 2018-03-25 at 10.52.56

 

It’s Not Limited to UI

SkinModifier defines how it affects the SkinComponent and its attached GameObject, actually, it’s not limited to only modifying UI components, it could do anything!

In this example, I created a new type of SkinModifier that can affect the rotation speed, and then change the rotation speed of the cube by switching the class of the cube between “slow" and “fast". When the class of the cube was changed, SkinManager will find proper SkinModifiers and apply to the cube.

speedgif

Conclusion

By applying the UI Skin System to our project, it benefits us:

  • Uniform color, size and other style settings
  • Much easier and faster to modify UI style at once
  • To have the ability to change the theme at runtime

But just like CSS, we still need to think and manage the structure of classes/selectors, or there will be a lot of SkinModifiers in the SkinAsset.

I also put the source code of the UI Skin System on GitHub.

If you want to know more about ScriptableObject, the following video is a nice speech about game architecture with ScriptableObject.