Okay, now that we have a functioning power up, we'll have to find a way to display the power up meter so we can see how much juice we have and so on. So let's start by creating a new GameObject, calling it HUD, for Heads of Display. So HUD. And we'll also want to create and attach a script called HeadsUpDisplay, let's do that. Let's open it up. In this script, we'll just want to output a simple user interface text, so instead of using the Update() method, we'll instead use the OnGUI() method that's also part of Unity Engine, and use the GUI class to create a label for the text. And so I'm going to read here from the official Unity documentation, the definition of OnGUI() so we kind of have a working definition to start off with. OnGUI() is called for rendering and handling GUI events. This means that your OnGUI documentation may be called several times per frame, one call per event. For more information on GUI events, see the event reference.
If the MonoBehaviour’s enabled properly is set to false, OnGUI() will not be called. Alright, so basically OnGUI() is run in a loop, very similar to the Update() method, but not so tightly bound to the same one call per frame specification of the Update() method. Otherwise, it looks like it will be a good place to put our event-based UI stuff if we had them like buttons and menus and that kind of stuff. So we don't really have that right now, but it looks like OnGUI will also serve us well to output our text labels with some of our HUD information. So we can go about creating the label in OnGUI() by calling the static label method found in the GUI class. We're not going to need that, so just write in void OnGUI(), actually it's all capital GUI. G-U-I. So I made a mistake with that and didn't realize why it wasn't working. Simply reference the GUI class and the Label() method and let's go up and down to see the different options available to us. Kind of try to make some sense out of this.
Now, the fact that we can access different versions of methods is something we haven't really talked about yet, but you probably already noticed the option of accessing seemingly different versions of the same basic method. This is part of a C# concept called overloaded methods, or method overloading. We've seen this many times on the calling side, as I would say most of the methods defined in Unity have several different definitions that accept different input parameters, right? But we haven't seen how method overloading works on the definition side of the equation. Simply put, method overloading is creating several versions of the same method, same in that it has the same name at least, but the implementation details are perhaps different in some way. But the obvious question is how does the compiler know how to tell them apart if they all have the same name?
Well, the answer is that the method signature is what the compiler really looks at to differentiate these similarly or same name methods. As long as the method signatures are different, in particular the amount and type of input parameters, the types used in other words, it's considered a different method by the compiler; although nonetheless grouped in with the other methods of the same name for convenience. For example when accessing IntelliSense. Let's demonstrate really quickly how you can do this by going back to one of our test scripts, and writing in an overloaded method definition. I want to go to the class Person, Person class and let's just create an overloaded definition of this DoAging() method. Really easy. Just go public void DoAging(), so it shares the same name. And we'll differentiate this one with a different method signature as the original, empty input parameter version. Say amount.
Now the important part here is the type in the input parameters, or the lack thereof for this one in differentiating these two methods and therefore being overloaded. The identifier, or the name for the local variable, it doesn't have an impact on this method signature, neither does the return type so it's basically the amount and the types of the input parameters. If I had a third method called DoAging() and I had a string p, whatever, that would also be a valid third overloaded method. Just sticking to one overloaded method just to demonstrate this, let's just go ... This would be how maybe the implementation details might differ with the different versions of the method, so this is pretty intuitive I think.
If we go to the Person Factory Class, it doesn't really matter where, we're not going to actually keep this, but just for demonstration sake let's call from either one of our instances the DoAging method, and then there you go with Intellisense it gives us the option either one with the single integer input parameter or no input parameter, right and so if we put that in there it will know that we're referring to the second overloaded method, the one we just created. Alright so I can run this, but I'm pretty sure you know what will happen. Let's get rid of this right here. We probably won't be making many overloaded methods or maybe any at all for this project, but I thought it was something that you should know, having come to see all of these overloaded methods that Unity provides.
Unity has a lot of overloaded methods that it hands over to you and it's just worth knowing how this works in the background. Now having understood overloaded methods, let's see what kinds of Label() methods we have at our disposal and try to better understand how to work with it. Back up to HeadsUpDisplay. Just going to get rid of these, don't need them right away. Alright, so let's go through these. Up and down on my keyboard here, let's see if there's anything familiar we can work with. I see something called a Rect and some string inputs.
I think this second one is probably good to start, because it's really simple. All we really need to do is just output some text, so it takes an a Rect call position locally to this method and a string. All we really need is just a section of the screen where we output our power meter integer. We can just convert that to a string easily, so I think this method will do, but another thing that pops out at us is we need a Rect. What's a Rect? I don't really know ... Well, I've used this before so I kind of know, but ... so let's just do what's most obvious when exploring.
Let's type in New Rect and see if its constructor can give us any hints when trying to formulate our Label() call here with something useful, when trying to figure out what a label takes in as input arguments. Let's say new Rect() and through IntelliSense see what the constructors give us. Alright, yeah, so this looks familiar. An X, Y floats as well as width and height creates a new rectangle. This is something familiar to us. An X, Y position on the screen in other words that also asks for the screen's width and height. So all floats, this is familiar to us, so let's try this.
Let's say X 15, whatever that position means on the screen, and 15 for the Y. So I think that will be in the upper left-hand corner, and let's pass in the width of our screen, which is available through a property called width. Alright that's a float and Screen.height for the height. And for the string, let's just type nothing particular in. Just say test, let's just see how this works. Well, so again I'm going to use this odd way of creating a method call with all this is all on different lines here.
The first argument is here, separated by a comma is the second argument and then the right parenthesis on its own line with the semicolon termination. This should hopefully give us an output that says “Test” in the upper left-hand corner if we're understanding this right. Let's just run this. Save that, and I think it's about time we disabled the sphere here, because we don't really want to ... The script in other words, it just gets out of our way. So we want to test out what we're doing. I never did put the script on the HUD, so of course do that. And let's see what's going to output here. I can barely make it out, I think there's something there. I guess it looks like there is ... the color is clash and it appears as though it's defaulting to a white text.
Alright, so if you want to change the color of your text, I mean I'm not going to worry too much about how the text appears, and we're just going to keep it really simple to output information to the screen, but here's an easy way on how you can change the text color. Go back here and right here in the OnGUI() method we'll just say GUI reference to class and content color and we'll assign to it a color. Before I do that I'll just hover over this, see it's a color, it's a type color, so we're going to need to give it a color, see what's available to us. I don't know, I'll just make it blue, right? That should stand out.
Now let’s run it, let's see if it's working. Alright, great, it looks like it works. So the next thing we want to do is replace this temporary dummy text with our actual PowerUpMeter. Let's go back here, and instead of test we'll write in so we know what we're referencing, “PowerUp”. And we'll concatenate that with the PowerUpManager.PowerMeter which is, what is it again? It's an integer, right? This is supposed to be a string. Well apparently this will work. It will implicitly convert it from an integer to a string, but in other cases where it's not implicitly converted, there's a very handy method available to the integer class or all integers in other words called ToString(), so I'm just going to call that at the end, to make sure it returns it's ring, right?
Let's try that. Yep, great. Looks like it's working. Alright that's pretty good, but I think we can add a bit of HTML-like markup and bold this text and make it a little bit more interesting. Let's wrap it in bold-type tags. And, well, this is going to look a little bit funny with all these concatenations and what not, so let's go back to ... Let's use the String.Format() method that we used before. Bold it first with the bold tag, and we'll want to have the placeholder for the first argument here, which will be the PowerUpMeter, and I'm doing this kind of in a funny way. Don't get too put off by my choice here. Alright, there we go.
I'll just keep that on one long line because otherwise it's going to look even uglier, but otherwise it should work. Yep, just a little bit bolder. Alright, so now we have the power up there, why don't we add the cool down meter to the GUI as well? We'll probably want to see that value because otherwise we won't know if we're cooled down or not, so let's just do this. Let’s just pretty much copy this right here. We'll make this below on the Y coordinate, say 35 for that. And we'll say “CoolDown: “ and then for that we'll want to reference the CubeController’s cool down, which ... Let's see, was it static? I don't believe so. We'll have to make it static. No, it's not, so let's just make it static. Then here we'll say, CubeController.CubeCounter, and then again we'll append because it's an integer, a ToString(), just to make sure, just to be explicit about it. I'm showing you that more so that when you do see that you're not confused. It's not often used in Unity, but it's a useful conversion method nonetheless.
Alright so everything looks like it's pretty good here. Let's just run this really quickly and see how the cool down works. First I'll let the power up count down, yep and the cool down is also working well. Awesome. Well, now that we have all this information outputting to our HUD of sorts, we can now clean up all these Debug.Log() references because we don't really need those, so here's a little handy way of doing that. You can just with Control+F anywhere here in Visual Studio, we can try to search for the entire solution for references to the Debug.Log().
Alright, so here I'll say entire solution. And there we don't need that anymore and the PowerUpManager, we don't need that either, and I think that's all we're really looking for right now. Save that, make sure it's all saved. Now that we've effectively created some sort of UI display here, we can always come back later to the script whenever we want to output some more information. I think later on down the line, we'll want to create a scoreboard for instance. But for now, I think that's in a good state and we'll move on to solving more problems in the next video. I'll see you there.
Lesson 33 - Displaying Text, OnGUI, Method Overloading