Become familiar with Unity's UI system
Create an entire game using the UI for all of its visual aspects.
Apply all of what is learned in a real world scenario.
Learn to think like a UI developer.
This video we're going to take a look at the visual aspects of the system. In reality the US system really plays down to two things. Images and text all the widgets that you see or that you could even create are going to be a combination of images and text. So everything from a slider to a button to a button to attach a view to a chat window to an inventory window. Just some sort of combination of images and text. So in this video I want to talk about how we can go about working with images and text. In addition I want to talk about things like our canvas groups or canvas render and order and layers and all that fun stuff so we can see how it is the new Gooley system goes about constructing the visual representation of our objects. So the first thing to start off with is the image because I think the image is really going to be the fundamental building block that we're all going to work with when putting together our goolies images are going to be everything they're going to be or buttons they're going to be our panels they're going to be our sliders and the way that we can use images is actually incredibly flexible. As you saw in the first video we actually can do really fun stuff with images in regards to filling or tiling and we can even incorporate the concept of fixed borders preserved aspects. All this fun stuff that we can do with one simple component of course actually work with the component we're going to need to bring in some images now like you saw in the first video there are some images that are already available to us and those images are what are used to construct the default unity Gilley. However I'm not really particularly interested in just showing you guys how to build a Duey that looks like you know the stock you know unity Gooley because well really that's not very exciting. So what I'm going to do is I'm going to bring in a couple images and I'll show you guys how we can use custom images with our image components. In reality the process is the exact same with the exception of there is going to be some considerations we'll have to bear in mind during the inport process. So I'm going to go ahead and fire up a Explorer window that's over here on the assets that are included with this series and I'm going to grab our three pieces and I'm going to dump them right into our assets. So I just click and drag and brought them over to the project window. So what that effectively did is it imported three textures because really textures are going to be the default things that that that images are imported as with unity as we'll see very shortly however textures will not be usable with in the image component of the new Gooley system. Instead we're going to have to import them in as a special sprite. I'm going to go ahead and do that on the panel select the panel texture. I'm going to go to the texture type and I'm going to select sprite do not spread select edited or Gilly and legacy Guly because that won't work with the new system if you like Spryte it'll work with both the 2d tools as well as the UI tools. Seeing as the 2d tools are are largely constructed or the UI tools are largely constructed from the Tutu's tools that makes a whole lot of sense. So I want to set that over that and I'm going to apply. Now there's a bunch of other options we can play around with when importing a texture such as borders and we'll look at that very shortly. But for now we just want to get the minimum in place to be able to show something visually on screen. So what are we to do now. Is it going to go over here to my hierarchy. And I'm going to right click on any of this white space and I'm going to go down to you. And I'm going to take canvas and just like in the previous video I'm going to leave this as a screen space overlay. So now that we're in the canvas Let's go ahead and create an image. You might say well I can just go ahead and click and drag a panel and plop it on to the UI and hey look it showed up it's a little small Let's just scale it up a little bit and yeah that would work but that's not actually adding it to the gooey system itself. So what you just did is if you just follow that step of clicking and dragging that's just going to add the image as a sprite Redner as you can see and the specter on the right hand side. That would be something you would use if you're for example building a 2D game. So I'm going to delete this and instead I'm going to go ahead and construct a goofy image. So that my canvas I'm going to right click select UI and go down to image know we've all seen this before already. But I want to go ahead and just point out the elements that we haven't talked about yet. We've discussed the transform. You'll notice that when you bring an image it does behave like a button by default in that the anchor is in the center of the parent. But you'll notice a couple of other really important components. First of all we have the canvas render. Now interestingly interestingly you say that word. You can't disable the canvas render it just kind of there but if we did remove it it'll say we can't remove it either. Oh because the image depends on a dirt of course. I wonder if we disable that now. Anyway the point is that the canvas render is going to be it's going to allow this game object to be represented visually is the best way to put it. The canvas render has no properties as you can see at least no properties that we can edit directly from the inspector. There are some properties that we can edit from code but we're not going to worry about those because in reality the canvas renderer just facilitates some low level drawing capabilities on the game object itself. It's just you think of it like like in a supporting role for the other components that might actually present something visually. So you'll always need a canvas render when you want to visually represent something in your gooey but a canvas render in and of itself isn't going to do anything because you'll need a component that actually uses the canvas render to draw something onto the screen. So the component that does that in this particular case is the image component as you can see right here Naledge component is made up of a variety of different properties that control the way an image is displayed. So what what what what images do we want to display what's the tint color. What material Do we want and so on and so on. Lots of fun stuff with the image component for the source image. I can click this little Certainly doohickey and I get a nice little list of all the things that I can choose for it. For example I could select panel which is the asset that I imported or I could select any of the existing assets that come courtesy of the Gooley system. So if we say look panel we could have also KRAD panel from our project window and plopped it on there as well. So now that we've selected panel we see we have color material image type and preserve aspect. So let's see what happens as we click and drag this panel around. As you'll notice it scales in a way that we would expect an image to scale. So basically what happens is is the direct transform determines the size and the position of a rectangle and then the image component will fill whatever selected image we have in that rectangle. So it's pretty much that. I mean it's pretty straightforward. And so as you'd notice by default stretching occurs there's a variety of different techniques of working with stretching. So I want to address stretching first and the concept of the aspect ratio. There's going to be a lot of situations when working with UI that you will definitely need lots of control over the way that that image is displayed to the end user. Because for example. Well because honestly I mean in the last show we spent the entire video talking about how we can stretch elements based off the width and the height of the parent. I mean obviously that means that we're going to have to take a lot of consideration into how our in size and how they size visually as well. So what we could do in this case is a naive thing would be to hit preserve aspect now preserve aspect is a very very handy option for a variety of circumstances. And you'll notice that does prevent distortion for our panel. So if I uncheck reserve aspect we get distortion if I check because of aspect. Basically all it means is going to fix the object within the rectangle the best that it can while preserving its existing aspect ratio which will guarantee no stretching. But there's actually another way to go about handling stretching that's built specifically for you guys. You might be familiar with the concept of a border from the last you system we could specify image borders which were portions of the image that were blocked off from being stretched in particular ways. See we can see here that the borders if we'd have preserve aspect unchecked get thinner as that gets smaller and wider as it gets bigger. This is a behavior that we don't want. What we really want to have happen is we want these borders these little doohickey things on the left and right hand side of the panel. We want them to stay the exact same. And the only thing we really want to stretch is the center of the panel. To do this there it's really just a two step process. Basically we have to actually change the inport settings from the asset itself. In the old Gucci system we would constantly have to tell at the border of a background image and that was really annoying. I don't know if and I don't know how many of you guys spent a whole lot of time with the legacy immediate. But you had to have a border with an image and you used it a bunch of times and maybe a couple of different goofy styles it got really really really annoying have to repeatedly tell that what the board or pixels were well in the new UI you actually specify the border of a background image on the asset itself as opposed to on the gooey. So let's do that first. Like I said this is a two step process. This is the first step. We'll go over the next step after this to specify the border of an image. We click on the asset inside of our project window and we go up here to spray mode and we make shirts single you won't be able to specify borders with multiple Then once on single we go into the sprite editor. Now inside the sprite editor we can modify the pivot as well as the border and I actually did misspeak here a second ago. You can specify the border and multiple. It was just there and I was clicking through that I was like where does this and where you specify those and just fill the void with words say something stupid. And I said something stupid. Yes you can have multiple sprites that specify the borders but so how do we specify borders. So what we can do is we can change these numeric values at the bottom and the borders are going to be zero up to the width of that image or the height of that image. We can also do this visually by clicking and dragging on these green little handles. So what exactly is the border. Well like I said before the border is going to determine where the image is allowed to stretch. Basically we want to prevent the image from stretching in particular spots. So we do that by setting up a border in such a way that we encompass particularly particular bits of the image inside of that border. Now to do this it's really handy to get to know the Spryte editor a little. So I'm just going to go over two of the really quick shortcuts or at least mouse movements that we can use to make this process easy. First of all we can zoom in and then we can hold down the middle mouse button to pan. So pretty straightforward stuff or a standard as far as two dimensional toolkits are concerned. But I just wanted to point that out in case you guys know because what we really want to do here is you want to zoom into the top part of this image then we want to grab the top border and move it down until we get into the center of the image which is about there. Then I'm going to scroll out and do the same thing on the left border. I'm going to move the border in right and tell there. Now I'm going to do the same thing with the bottom border. I'm going to move it up until all the things that I don't want to stretch are encompassed by that border then I'm going to do the same thing on the right border already. So we're done specifying the border. This again will do is a little prevent the image from scaling are that the portions that we specified as the border and distorting them. So as always whenever we finish up with our spray editor we get to the top right corner. We had applied that and close this out. Now again you'll notice that we did apply a border but it still looks ugly. We still get distortion as we resized this in the x axis. So to fix that we need to actually tell the image script itself the image component itself that we're working with a sliced image. We do that by going to the image type and selecting sliced by selecting spliced. You can now notice that the borders don't get distorted they'll scale horizontally or vertically of course. But as we move them in the left and the right border don't change and as we move it up and down the top in the bottom border don't change. So it's a really handy way for putting together resizable panels and again allowing your eyes to be scaled up and down is pretty important considering how the transform is intended to be used. Already. So that's basically our sliced image. Now before we move on to other types of images that we can play with and before I move on slicing up our button and our head or I do want to point out one other thing and this is something that I always like to include in all the training that I do with unity and that is that game objects are not special when you create them from a menu. So what I'm about to show you is how you go about constructing an image in visible image from an empty game object. This will help for both people who want to be able to script this as well as hopefully drive home the point. That's the only thing that makes this an image and not an empty game object is its canvas render and its image component. So what I'm going to do is I'm going to reichlich canvas and it's like create empty which will create me this empty game object right here. The game object has a wreck transform because it exists under canvas. I'm going to give it a canvas render by hitting add component canvas render. And you'll notice that nothing happens. That's again because the canvas render is a utility component that's used by other components to present visual information. Then I'm going to add a component. I'm simply going to do image that I'm going to take the source image and I'm going to like panel and because it detected the existence of borders it automatically selected the image type sliced already. So let's go ahead and quickly go through our button and hetter and get those sliced up just to show you guys an example of how to do that again. So I want to go into hetter to click on the image in my project window I'm just like texture type Spryte. I'm going to open the sprite editor and I'm going to create a border out of this. So I'm actually going to specify the border to be then when I go to the top right or sorry I need to specify that as a border as well. So we don't get any distortion then but of the top right hit apply. Close out. Now I want to click on button. I'm going to get a texture type. I'm going to select Spryte Tuti and you I go into the sprite editor and I going to specify the border. They really couldn't have made this easier. If you're again if you're familiar with the old gooey system this should be very very nice. Apply again. So now my button in my head are done. Let's turn this guy into a header to do that. I'm going to select him. I'm going to click and drag header from project into the source image. Now we have her header. You notice that it lacks distortion at least almost entirely. So it's go ahead and make our panel maybe a little bit bigger and drag over better. All right so now we have kind of a panel and a nice little header inside of it. So it was a couple of other cool things we can do with images. One of them I already showed you guys earlier. And these these things are pretty self-explanatory so I just want to kind of gloss over them shall you guys they exist so that you are familiar with them enough to remember that they do exist. So I'm going to do is I'm going to take this game object I'm going to duplicate it and I'm going to move it over to the right hand side. Then I'm going show you the different other kinds of images we can do. We can go to tiles which does exactly what it says it does. The tiles the image you'll notice what's interesting about tiles is it is taking our border into account which will allow for some really interesting you eyes if the images were created specifically for this. So to show you guys what tiled would look like without a thing without a sliced image. Let's select checkmark for example and then let's select image type tiled. And so now we see a really basic tiling. So we could do this too. And let's say maybe a nice little texture to the background of a panel for example or something like that like a little grid texture a honeycomb text or something like that. There's a lot of use cases for this sort of feature. Then we also have filled which we already showed you guys filled in the first video. I'm going to go to source image and I'm going to select a panel and then let's just look at the different kinds of films we can do with it. I can do radio 360 which is the default. I can do radio 180 radio 90 and horizontal I can also preserve aspect in this node as well. If I wanted to which would be really handy for something like this but ometer I can change if I go to read radial 90. I can change if I want to go clockwise or counter-clockwise. So that's counterclockwise and that's clockwise. I can change it which direction I want it to fill from top left top right. Bottom right and I can do that on the other radials as well with a vertical I can change it from filling from the top to the bottom. Same with horizontal. I can move it from the left to the right. There's not really a whole lot to say about filled other than it's amazing. I mean if you guys again I'm saying this a lot but it's true if you guys have ever played around with the old system you can definitely see the value of something like this. You can build all sorts of stuff for speedometers health bars experience point bars. I mean the list goes on and on and on. I love like that. It just seems like such a really simple feature filled being able to have filled images but I can just think of a thousand use cases right off the top of my head. The second I saw that in the documentation but sorry I get a little excited about this particular image type But anyway so yeah we have that that's really it simple slice tiled and filled. They do what they say on the 10. Other than that we also have a tent color but that should be pretty familiar for anybody who's worked with gooey stuff before. As you can see we can tent the color of the panel. Of course that's a really cool feature because it will allow us to do is do some animation without affecting the actual material itself by overriding the color. So for example I could come down here and say Hannele color change. I could go ahead and put together a nice little animation thing. Maybe have a little bit brighter maybe go to is going to look ugly isn't it. There we go. And then maybe you go right there. So as you can see we can animate the color and achieve some really cool effects by doing that but yeah I mean I think that's that's mostly what I wanted to talk about with the image because again image is just what it is it's an image and it's going to be primarily what you're going to be building things with. So a little cool thing though about images is I'm going to go ahead and remove these three Then I going to reichlich canvas select UI and create a panel. In actual fact there is no difference between a panel and an image. Besides what default parameters are given to it. So I wanted to point this out because I really want people to start understanding that the way this UI is constructed is is so that you could build complex widgets out of simple concepts and a panel again is nothing more than an image with some default parameters set up you know you can tell it's it's sizing is different it's anchoring is different. It has a different default image a different color but it's really the same thing. It's nothing more than an image. Right. So that's all I really wanted to say about images at this point. So let's move on to text. So text is going to be another thing that is going to be really important for how we present information to the user and it is really the second primitive. So if you can think of the image as the first primitive the first atomic unit of constructing visual eyes you can think of text as the counterpart to that. So to create text we can just right click like let's say our panel go to UI and select text. Yeah it's really that simple. And if I wanted to create text manually I would right click panel select or select create empty. I would add a canvas render to it. Then I would add a text element to it and then I would type in text so again nothing special text is really just a component that gets attached to a game object that has both direct transform and a canvas render the transform behaves exactly the way you'd expect. Transforms don't change in their behavior. No matter for working with text or images. So as far as the actual text component goes we've got some pretty straightforward properties on it. I mean there's not really a whole lot to say. We first of all we got our text which That's the text that's that's going to be rendered. And we got our font then we got our font style you know we can have a bold metallic bold and italic if you want. We have our font size we have line spacing. We have Rich Text which I'll talk about rich text here in a second. We also have our alignment. So if anybody has worked with any sort of ghillie framework ever this should look pretty familiar here we have our horizontal overflow. So in this case we can see an example of horizontal overflow right there. And then what we can do is we can say overflow instead which will cause the text to appear outside of the edge of the transform or we could have it wrap like is pretty much what we're typically typically going to want to do. And then finally our vertical overflow we have truncate right now which truncate we'll just make the text not appear if it is past the vertical bounds of the transform or we can say overflow which gives us the same behavior that we saw before with our other overflow than we have best fit which simply figures out the best way to do that. The best way to fit that text within that space it allows us to give an image size and a max size so for example if we set them in size like for me we get some different behavior with our then we have a color not much to say about color it's the color of the text and we have the material with materials we can do fun stuff with it. We can set up different materials if we want to. Using different Spryte materials different materials and so on. And we we're actually going to talk about materials here in a second or I don't know. I mean text materials will have different constraints on them and you can certainly create some special effects using different materials but the majority of the time you're not going to want to worry about it anyway. So that's really the majority of what a text component does not a whole lot say about it other than our rich text. So rich text allows us to do is it allows us to specify some additional formatting values within the text itself. So imagine that you have a chat box and you're wanting to highlight certain text or change the color of certain text but not the whole what is going on with my canvas. Now my game window is being problematic I going to move it in there for now. So to use Rich Text we simply use a subset of basically HVM out. So I can say this is some normal text and this is called. So you can see right there that by adding in this little bit of markup is bulled is now in bold. So we're changing the properties of the text in the middle of the text itself. If we disable rich text you'll notice that it's printed out verbatim and the tag is included with that. So we can do bold. We can do a taluk we can do bold and italic pretty much all the combinations that you'd expect with that we can change the color so I can say color equals red and you'll notice that with this bit right here I say color equals red. That's small divergence from actual HD M-L because anybody who's written HDL would say well that's obviously an improper attribute right there. But I mean is close enough to where I believe the analogy is appropriate. So in this case we're changing the color red we can change the color to pretty much any hex value we want like some sort of dark or gray or green or whatever and it works just like you would expect if you're writing this yes we can also do size. So size equals 20 let And that's actually kind of small. So I want to do like 50. So as you see we can add in this markup and pretty much modify the parameters that we're interested in modifying. Another interesting thing that we can do is actually specify the material of a text but we're not going to worry about that again because it's going to mostly be applicable to text messages and not necessarily the text that we would be displaying here. O'REILLY So I mean that's text. I don't really know what else to say about it other than these properties are all pretty self-explanatory. The way that it's positioned and sized is exactly what we talked about before with the way the transform works. OK so again we we've now talked about our two major primitives are images and our text. And you'll notice that every single UI component is going to be a combination of one of these two things. So for example I'm going to remove both of these text items then I'm going to reichlich panel go to UI and create a button. Now ignoring all the buttons specific stuff in this game object you'll notice that really all the button is is a game object with a image component on it with a child element that has a text component on it. And we can see this on everything that we do. Let's Chris slider slider. So that's what a slider looks like looks super complex right. Well you'll notice the slider has an image for the background. Right. A sliced image for the background. Then it has a fill area which is just an empty game object. Then it has a fill which has an image in it. Then it has a handle slide area which is an empty game object and has a handle thousand images that honestly the slider is just a bunch of images and that's it really what the way that the images work with the new system. You can accomplish pretty much any visual in any visual Inus you want to using any sort of combination of these techniques. So there are a couple of things that I want to address before we sign off on this video and that is the ordering of elements and how they appear above each other. And the second is going to be a very simple component called a canvas group. So let's first talk about our ordering. So I want to create this panel and I'm going to move the buttons so I mean how the button the slider inside the panel. I'll go ahead and center them so they move along with the panel. Move the button up then I'm going to change the background color of my panel and you'll notice again the panels just an image. And I'm just changing them serials color so I'm going to change it to some sort of reddish color then I'm going to Right-Click canvas and create another panel. I'm going to go ahead and center it and resize it. That I'm going to change its color to some sort of bluish color ok. Ordering is really simple. Basically it boils down to which element appears above which other element that is determined by the order inside of the canvas. Let me go ahead and make this complete. Both of these panels completely opaque. So it'll be even easier to see their order while that's hurting my eyes. OK. So now both panels are completely a pair. We can clearly see that the blue panel is above the red panel we can switch that up by changing the order. Now the red panel is above the blue panel. It's that simple. There's really not a whole lot else to say about ordering. It's determined by the order in the hierarchy and that's it. OK one last sort of loose end in regards to how elements are visually rendered. So again this whole lesson has been about how elements appear visually through text and through images. And those are really the only two things are going to work with. But there's ways to override certain parameters of an entire group of elements. And there's also a way to apply certain effects to certain elements. So let's first address opacity and interactivity. We'll talk about that as well. So in this panel let's say I want to faded out to nothing. I want to make the Abassi the panel to zero. Well the first thing we might do is we might go oh that's easy. I'm going to take this collar and I'm going to let you pass it down to zero Well the problem with that is that our child elements are still visible. And in this particular case I was hoping that they would disappear along with the panel. So we can't do that. So you might say well I could just do it I could just animate it so the panel disappears and then the button disappear or wait the button has text in it doesn't it. OK well I'll make sure text disappears and then we have to make for. Oh wow that's a lot of things to do. And you'd basically just be running down an incredibly unmaintainable path trying to fade out a panel and all of its children to zero opacity. However this is such a common thing that you would do. That's actually very easy to implement. Inside the new Guly system within the form of a canvas group. So what I can do is on this panel I'm going to add a component and I'm going to say canvas group inside this canvas group. I have three properties Alpha inner actable and Bloch's Ray cast's. We're not going to worry about Bloch's recaps at the moment interactive all is really cool because it allows me to disable the interactivity of every single UI element inside of it. So notice as I'm unchecking this the button is growing out that's really important. A lot of eyes will enable or disable many controls at the same time by using a canvas group. We can accomplish that but that's not what I want to talk about. I want to go out and talk about Alpher which doesn't require a whole lot of explanation because as you notice I can drag it down and back up and the panel appears and disappears. It's that simple really. So it's an animated property. You can throw it to your animator you can create a cool effect for a panel swooping in from the Z-axis and fading in or fading out or whatever. It's an incredibly important technique that will allow for a variety of different visual effects. Speaking of visual effects there is one more thing that I want to address. So what I'm going to do is I'm going to reset this panel back to white and I'm going to bring its alpha down a little bit. There's a handful of different effects that we can apply to our all of our elements to have canvas renders on them. In fact the Guly system is extensible enough to where you can write your own effects if you want to but a couple of built in effects are going to be located under component UI and we're going to have our effects right here. So here we have position as U-V one won't worry about that that will affect how Schrader's work we have primarily outline and shadow. So an outline as you can see I have created an outline of the button let's that on text someone to remove that component and I'm going to create on this panel a text and let's create an outline on it. So when I type in outline they enter and now you can see it's a little bit a little bit more of an appropriate effect. So as you can see I can kind of change the color. I can move the outlines around. I mean honestly these effects I think the biggest potential for them is that the fact that they exist and are extensible and you can definitely plug into this API and do your own modification the other effect that we can look at is shadow which does exactly what you'd expect it to. It creates a drop shadow so you can change the dropshot a distance and it really just as you can see creates a shadow that you can change the color of. It's really not that super fancy it's just going to create that using the alpha values in the shape of that element to create something rendering behind it. So yeah that's really about it. So again in this video we showed you guys images primarily the different kinds of images. Everything from simple sliced tiled the filled and how you can create a variety of different effects using images. We talked about text and not a whole lot to talk about with text. You have pretty straightforward properties that do what you expect them to do. Then we talked about léa ordering which is going to be really important for a variety of different situations. We'll definitely have more discussions about how to order things properly in later video series because it'll come into play especially when you're trying to do something like a inventory window that overlays all of the elements and so on. So and then finally we talked about simple effects that we can apply and really those effects I just threw them in this video and this for the sake of completeness because I don't find them particularly interesting. Anyway I hope you guys enjoyed this video and we'll see you guys next time.