Creating Custom GUI Skins PART ONE

Discussion in 'UnityGUI' started by Alismuffin, Nov 24, 2011.

  1. Alismuffin

    Alismuffin

    Member

    Joined:
    Oct 3, 2011
    Messages:
    95
    Hey everyone! I'm not sure if this tutorial will be helpful to anyone (and I probably did a million things wrong) but I couldn't find a tutorial like this already made. Hopefully it will help at least some of you in one way or another!

    In this tutorial I'll be walking you through the steps of creating your very own custom GUI/menu elements for use in Unity3D.

    Before we get started, here are the things you will need to follow along:
    Photoshop/Paint.NET/Gimp/Other image editing software
    Unity3D
    Creativity

    A quick introduction into Unity GUI Skins

    GUI stands for Graphical User Interface. Think healthbars, score, maps etc.

    When writing GUI scripts for Unity3D, the default skin is used unless told otherwise. The default skin looks like this:
    [​IMG]

    The cool thing is that you can make all the elements look completely custom! To do that you will need to create a NEW GUISkin. :D

    Creating a New GUISkin
    To create a new GUISkin it's quite simple. All you have to do is go to either the Assets Menu:
    [​IMG]

    OR the project tab:
    [​IMG]

    Click "GUISkin" and you will see a new icon in your project tab called "New GUISkin".
    Rename it accordibg to it's purpose. For example, I will rename mine to "Menu GUISkin"

    So let's move on to actually creating the images that will be used for our GUI skin!

    First let's create a Folder To Hold our GUISkin Images
    This is pretty straightforward. I named my one "Menu GUISkin Resources"
    I would also recommend creating another folder called "GUI Components" and placing EVERYTHING to do with your GUI inside that. Just for organisation purposes!! :)

    Now Let's take a Look at our GUISkin
    Clicking on our Menu GUISkin will display this in the inspector window:

    [​IMG]

    (Ignore the Fonts folder and GUITestScript for now!)

    These are all the components that make up a GUISkin in Unity. You have options for all the elements such as buttons, boxes, labels and scroll bars!
    If you expand any element, you will see a whole heap of options which you can change. However, there is no point in us changing it right now because we don't actually have anything setup to preview it!
    I wrote out a code that you can simply copy paste into a new JavaScript:

    Code (csharp):
    1. var MenuSkin : GUISkin;
    2.  
    3. var toggleTxt : boolean;
    4. var toolbarInt : int = 0;
    5. var toolbarStrings : String[] = ["Toolbar1", "Toolbar2", "Toolbar3"];
    6. var selGridInt : int = 0;
    7. var selStrings : String[] = ["Grid 1", "Grid 2", "Grid 3", "Grid 4"];
    8. var hSliderValue : float = 0.0;
    9. var hSbarValue : float;
    10.  
    11. function OnGUI() {
    12. GUI.skin = MenuSkin;
    13.     GUI.BeginGroup(new Rect(Screen.width/2-150,Screen.height/2-150,300,300));
    14.         GUI.Box(Rect(0,0,300,300),"This is the title of a box");
    15.             GUI.Button(Rect(0,25,100,20),"I am a button");
    16.                  GUI.Label (Rect (0, 50, 100, 20), "I'm a Label!");
    17.                      toggleTxt = GUI.Toggle(Rect(0, 75, 200, 30), toggleTxt, "I am a Toggle button");
    18.                           toolbarInt = GUI.Toolbar (Rect (0, 110, 250, 25), toolbarInt, toolbarStrings);
    19.                              selGridInt = GUI.SelectionGrid (Rect (0, 160, 200, 40), selGridInt, selStrings, 2);
    20.                                  hSliderValue = GUI.HorizontalSlider (Rect (0, 210, 100, 30), hSliderValue, 0.0, 1.0);
    21.                                     hSbarValue = GUI.HorizontalScrollbar (Rect (0, 230, 100, 30), hSbarValue, 1.0, 0.0, 10.0);
    22.                                         GUI.EndGroup ();
    23. }
    And seriously, unless you are familiar with GUIScripting, just ignore trying to figure out that code for now! I will be writing a GUIScript tutorial in the future to help with that :D

    Ok so attach the new javascript to your MainCamera, and drag the Menu GUISkin into the MenuGUISkin variable of the Main Camera.

    Click play now and you'll see that the skin is the same as the default skin right now. Obviously we don't want that so, starting from the top we'll create our very own GUISkin!

    Font
    This is the global font for the entire Skin. Each component has their own font element as well, but if the majority of your skin uses a particular theme, it is best to set the Font up top as that Font! The individual Font options will override the global one. Think of it this way, if the button/box/etc has not got an individually defined font, then use the globaly defined font. If it has an individually defined font, use that font for this element.

    Importing fonts is pretty straightforward! You just need to put in any .ttf OR .otf formatted fonts into your project tab in Unity!

    You can actually drag these straight from your fonts file of your computer:

    [​IMG]

    And now you can click the little circle with a dot next to Font in the GUISkin and assign any font you want!
    To quickly preview these fonts, you can actually press PLAY for the game and as you change fonts it will update in the game view! Handy right?

    [​IMG]

    So that's how you change the font that the Skin uses, but what if your font is too big? Or you want it italicised, or bold?
    Well you may have noticed already, but when you imported your font, it actually came in with adjustable properties which you can access by simply clicking on the font and looking in the inspector window:

    [​IMG]

    More information about fonts here!

    Ok so moving on we'll be having a look at boxes, and we'll actually be using PhotoShop to create our own here!

    Boxes
    You're going to want to pull PhotoShop or similar(Paint.NET, Gimp etc) out for this part!
    Ok so let's have a look at our box component:
    [​IMG]

    It has many different dropdowns, but don't be daunted! They're mainly for the different states of the box and you actually are not required to create an image for each one.
    For example, normal refers to the state of the box when nothing is happening to it. It hasn't been pressed, the mouse isn't over it and it's simply in a state of normality.

    Let's create a box background image for it's normal state first!
    Ok so a good way to go about this is the live update method:

    1. Open up Photoshop
    2. Create new image
    3. Save as BoxNormal into the "Menu GUISkin Resorces" folder we previously made
    4. Click the dropdown arrow for Normal under the box category and assign your newly saved image to it's background texture
    5. Put photoshop on half the screen, and unity on the other
    6. Push "Maximise on play" and PLAY on Unity
    7. Start drawing your background on PhotoShop

    Your setup should look similar to this:
    [​IMG]

    Now what you need to do to see how it looks on Unity is save, then click the unity window. This way you can quickly check out how it's going to look on unity! :D

    For the box example Im going to create a basic box style.

    After drawing out a nice border for my box I ran into the first issue:
    [​IMG]

    What the heck is going on? Unity is drawing out the inside fuzzy!

    Well you see, Unity stretches the inside out so as the size of a box is dynamic. A good texture will be drawn so as it works at any size. This doesn't mean we can't have borders though! It simply means we have to tell unity that there is a border in our texture. We also have to tell Unity how many pixels the border is. To do that you go here:
    [​IMG]

    I measured my border distance to be 7 pixels from each side. Putting in a couple more pixels gave the desired result.

    have a look at the fixed side compared to the non fixed sides:

    [​IMG]

    Here I set the left border and top border to 9.

    Looks a lot better right?

    But hang on! If Unity stretches the texture, why have we drawn such a big texture? It's pointless and will only increase loading times even if ever so slightly. A better way to draw this would be:
    [​IMG]

    Another good thing about making the texture smaller is that now I can input the border size of 7pixels and it will be fine. I acyually don't know why this is admittedly :p

    What we can now do is fill in the middle of the texture and even between the border lines to give us a solid style:

    [​IMG]

    I used random colours here just so you can clearly see what affects what.
    Alright so say we want somewhere to place our box title. How would we do that?
    It's actually pretty straightforward. You just increase the height of your texture and input the new border distance from the top:

    [​IMG]

    Messing around in PhotoShop and with the Unity settings you'll be able to come up with all sorts of results!

    [​IMG]

    For this style, what I did was I made the centre transparent. To do this I just created the middle section on a different PhotoShop layer and adjusted it's opacity value.
    I also used layer styles to bevel my box in certain places.
    The border sizes are the distance form the edges of the canvas to the green centre piece!
    Another thing I did was I imported two custom fonts, set one as the default generic font at the top, and the other as the Box font. I also played with the content offset options to position my box title exactly where I want it!

    There is a problem however. Our problem is that the buttons and other stuff we have inside our box is not bound by it's border! To fix this, first go into the GUIScript I gave you earlier and paste this over it:

    [​IMG]

    Code (csharp):
    1. var MenuSkin : GUISkin;
    2.  
    3. var toggleTxt : boolean;
    4. var toolbarInt : int = 0;
    5. var toolbarStrings : String[] = ["Toolbar1", "Toolbar2", "Toolbar3"];
    6. var selGridInt : int = 0;
    7. var selStrings : String[] = ["Grid 1", "Grid 2", "Grid 3", "Grid 4"];
    8. var hSliderValue : float = 0.0;
    9. var hSbarValue : float;
    10.  
    11. function OnGUI() {
    12. GUI.skin = MenuSkin;
    13.         GUI.Box(Rect(Screen.width/2-140,Screen.height/2-140,300,300),"This is the title of a box");
    14.         GUI.BeginGroup(new Rect(Screen.width/2-140,Screen.height/2-140,300,300));
    15.             GUI.Button(Rect(0,25,100,20),"I am a button");
    16.                  GUI.Label (Rect (0, 50, 100, 20), "I'm a Label!");
    17.                      toggleTxt = GUI.Toggle(Rect(0, 75, 200, 30), toggleTxt, "I am a Toggle button");
    18.                           toolbarInt = GUI.Toolbar (Rect (0, 110, 250, 25), toolbarInt, toolbarStrings);
    19.                              selGridInt = GUI.SelectionGrid (Rect (0, 170, 200, 40), selGridInt, selStrings, 2);
    20.                                  hSliderValue = GUI.HorizontalSlider (Rect (0, 210, 100, 30), hSliderValue, 0.0, 1.0);
    21.                                     hSbarValue = GUI.HorizontalScrollbar (Rect (0, 230, 100, 30), hSbarValue, 1.0, 0.0, 10.0);
    22.                                         GUI.EndGroup ();
    23. }
    Ok now look for the dropdown under box that says "Overflow":

    [​IMG]

    I set my sides to 15 pixels overflow each. What this means is that where the box physically starts is 15pixels away from where it visually starts. This will ensure that we dont have to calculate the distance for each button or whatnot inside the box.

    So now this is what we end up with:

    [​IMG]

    Awesome!

    This is getting a bit long so Ill make PART TWO in another thread ^^
  2. Kokumo

    Kokumo

    New Member

    Joined:
    Jul 23, 2010
    Messages:
    390
    Alismuffin, thanks for this post.
    Despite of my knowledge in the design area (and, of course, in the development too), i can say that this first issue of your guide was extremely useful to me.

    :D

    PD: why don't you edit the first post to keep all together, instead of create another topic?
    Last edited: Nov 25, 2011
  3. DEtH_MoroZ

    DEtH_MoroZ

    New Member

    Joined:
    Nov 22, 2011
    Messages:
    42
    Thank you.
  4. DAEvo

    DAEvo

    New Member

    Joined:
    Nov 20, 2011
    Messages:
    12
    Thank you for this resource - very helpful!
  5. LaneFox

    LaneFox

    Member

    Joined:
    Jun 29, 2011
    Messages:
    1,289
    Thanks for the write up, made it quite easy to see how things work and how to customize the settings.
  6. Kokumo

    Kokumo

    New Member

    Joined:
    Jul 23, 2010
    Messages:
    390
    Thanks a lot! really useful.
    It deserves a sticky... don't you think?
  7. softwizz

    softwizz

    Member

    Joined:
    Mar 12, 2011
    Messages:
    740
    Pity you never did it was a good tutorial.
  8. dkozar

    dkozar

    Member

    Joined:
    Nov 30, 2009
    Messages:
    1,394
    + 1
  9. Joe Lauliet

    Joe Lauliet

    New Member

    Joined:
    Jan 27, 2013
    Messages:
    1
    Thank you!!!
    Very Helpful... :D
  10. BubbaManatee

    BubbaManatee

    New Member

    Joined:
    Feb 6, 2013
    Messages:
    1
    Thanks for the tutorial!!
    Wish there was more!
  11. Brastik

    Brastik

    Member

    Joined:
    Mar 12, 2013
    Messages:
    8
    Thank you for putting this all up. Was looking around for GUISkin example but found nothing easier to understand than this one.
    +1 for the Photoshop stuffs lol. I need that too
  12. kjsheppard

    kjsheppard

    New Member

    Joined:
    Mar 26, 2013
    Messages:
    3
    Thank you! Great tutorial.

    Wondering if anyone know's how/where you can alter the position so the gui is at the top left of the screen?
  13. mutazalhawash

    mutazalhawash

    New Member

    Joined:
    Oct 18, 2012
    Messages:
    21
    Awesome tutorial thank you :D
  14. Daiboken

    Daiboken

    New Member

    Joined:
    Mar 8, 2011
    Messages:
    28
  15. dkozar

    dkozar

    Member

    Joined:
    Nov 30, 2009
    Messages:
    1,394
    You could make a complex component which - besides a slider - renders ticks and labels with numbers.

    For labels you should have some logic (like in charting) which handles the label density - for labels not to overlap.

    Looking for a Flex-like component model? Check out eDriven. It has the slider "step logic" already in place.
  16. RaganorK

    RaganorK

    New Member

    Joined:
    May 18, 2013
    Messages:
    1
    Thanks a ton man.. this is a very useful and simplest thread....
  17. vfxjex

    vfxjex

    Member

    Joined:
    Jun 3, 2013
    Messages:
    34
    Thanks it was a very good tutorial
  18. bustedkrutch

    bustedkrutch

    Member

    Joined:
    Jun 24, 2013
    Messages:
    19
    This is an awesome tutorial. I'm not very "artsy" so the gimp part will be interesting but the rest is easy to understand. Thank you.

    Would you be willing to share the "boxes" you created so that an art challenged indie could use them :roll: ?

    Either way, thank you for taking the time to put this up :)
  19. mcunha98

    mcunha98

    Member

    Joined:
    Jun 13, 2010
    Messages:
    176
    I did some boxes using 32 x 32 pixels and changing the size of buttons in Unity and get the idea.
    [​IMG]

    In image above, I use a button or a label depends of the level's state. The dimension of button (BOTAOTAMANHO) is 32pixels, for the buttons where I need to give more effect, I used a large button to simulate the effect.
    Code (csharp):
    1.  
    2.             if (!mundo.liberado)
    3.             {
    4.                 GUI.Label(new Rect(mundo.x, mundo.y, BOTAOTAMANHO, BOTAOTAMANHO), imagem, guiSkin.label);
    5.             }
    6.             else
    7.             {
    8.                 if (GUI.Button(new Rect(mundo.x, mundo.y, BOTAOTAMANHO * 2, BOTAOTAMANHO * 2), imagem, guiSkin.button))
    9.                 {
    10.                     gameObject.GetComponent<AudioSource>().clip = botaoClicado;
    11.                     gameObject.GetComponent<AudioSource>().Play();
    12.                     Application.LoadLevel(nome);
    13.                 }
    14.             }
    15.  
  20. semmie1900

    semmie1900

    Member

    Joined:
    Mar 15, 2013
    Messages:
    23
    Good tutorial!

    I only walk into one thing, how do I use a texture as a background (like leather for an inventory), and still make it resizable?
  21. dkozar

    dkozar

    Member

    Joined:
    Nov 30, 2009
    Messages:
    1,394
    You should use the border feature of the GUIStyle class to get the scale-9 image effect.

    You should apply your style to GUI.Box or similar.

    If you want the tiled image, you should use GUI.DrawTextureWithTexCoords.
  22. zxprince

    zxprince

    New Member

    Joined:
    Jan 17, 2014
    Messages:
    2
    You are grate man.
    Thanks a lots for your this tutorial post :D.
  23. mariamh

    mariamh

    New Member

    Joined:
    Feb 26, 2014
    Messages:
    1
    Thank you so much, you should do more tutorials :)