Monday, September 14, 2015

OnGUI and the new UnityUI system

I'm going to fast forward a bit on this blog to the present day, or at least work I was doing today.  I mentioned before that I started Eruptoid back in the Unity 4.3 days.  Back in those days there wasn't a simple, easy to use, user friendly GUI design system.  Buttons were all created in code with an OnGUI function call.  Button and text positions were all determined in code, and called out sizes in pixels.  This is fine if you're programming for a single target resolution, but as soon as the idea of changing screen sizes enters the equation, all bets are off.  This was especially frustrating when programming for Android, since android devices at the time had screen sizes that ranged from 800x480 to 1920x1080.  So programming a button in the bottom right of a screen 800x480 would require completely different code than one at 1920x1080.  This forced me (and I imagine, everyone else) to do some major workarounds, or purchase 3rd party gui addons such as UGUI.  Here's an example of creating a button in the top middle of the screen that would reload the title screen:

if (GUI.Button (new Rect(Screen.width/2 - Screen.width/10, Screen.height/10,Screen.width / 5, Screen.height / 10), "Back to Title")){

Yep.  For each and every gui element I wanted to show on the screen, I had to do a relative position and size calculation manually.  It was tedious, slow, and obnoxious.  Plus, creating a style synergy between your GUI and the rest of your games aesthetic was a process I still don't understand.  So you end up with a pretty plain looking button.

Fast forward to today.  In Unity 4.6, they released a new feature called Unity UI.  It created a graphical user interface for the developer to implement a graphical user interface in their games.  Ground breaking stuff, I know.  It has a ton of features that were handled previously in an arcane style system known as a GUI skin.  Now each individual gui element can have its own style, and the workflow matches much of the rest of the Unity object oriented workflow.  Just drag and drop elements as needed into the inspector and the design area.

It uses a game object called a "canvas" to paint and position the UI onto.  The canvas can be relative to camera space, world space, or screen space.  And best of all, the Unity UI almost painlessly scales your UI elements flawlessly to any resolution.

I say almost painlessly, because there are still some things that feel like need a bit more work.  Text fields on buttons, for example, have an option to scale to fit, but don't have a very good way to constrain what area to scale inside of.  Obviously, text fits inside the button, but buttons can have different outlines/styles, and sometimes the text would end up overflowing outside the graphic for the button with certain styles.  I'm still trying to figure out all the nuance, but its a vastly improved system over the old.

Which brings me to today.  Today I spent most of the afternoon creating new borders for my panels and buttons, and the recreating my old OnGUI buttons and text fields into the new UnityUI version.  It makes things look way more polished than with the stock buttons.  To finish the example, here's a similar button now that does the same thing.

That border and background?  I made that using Blender.  It was a pretty simple process that I'll go into in a different blog post.  But here's a teaser screen shot.

I created a 3D lighted version of the border, and then rendered a 2D texture from it.  Blender is awesome.  Seriously.  If you have any interest in doing anything with art, from texturing to 3D modeling, to video editing and compositing, Blender is what you want to learn.

Blender blender blender blender.  Blender blender.  Blender Blender Blend.  Time for bed.