Working for the Clampdown is the title of a song by my favorite group. If you've never heard of The Clash, you should go check them out and then come back to this video. In this lecture, we're going to clamp the character's position so that it stays completely in the scene. We use the term clamp when we talk about keeping a value within a range of values within a specific set of values. Recall that last time we got it, so our character would follow the mouse around the screen, but the character can leave the screen. We want to clamp the character to stay in the screen. I've done some preliminary work including adding two scripts and modifying the character script to help us do that clamping. Let's look at that preliminary work first and then we'll actually implement the clamping. I have a ScreenUtils class, that's a static class that does not inherit from MonoBehavior. It's pretty common to write static classes that provide utilities like the math class and the console class. We're just doing a custom static class here with some screen utilities. Anytime a consumer of the class accesses a property of ScreenUtils, they'll start that access by saying ScreenUtils dop. I've got some fields that I've saved here. These first couple of fields are to support resolution changes. When you run a game in the editor, particularly if you don't just run it in the game window. If you maximize the game window when you run, it actually changes the screen resolution. This is just to protect against that and make sure everything still works properly. The stuff that we really care about here are the screenLeft, screenRight, screenTop and screenBottom field because those will keep track of the world location of the left, right, top, and bottom sides of the screen and we'll need that to be able to clamp our character. I've also implemented static properties so that consumers of the class can get all four sides of the screen without accessing our fields. Remember, these are not public because we believe in information hiding. This is how a consumer of the class will get screenLeft and we call this method to handle those resolution changes. But after we've done that, we return the screenLeft field. We do the same thing for screenRight, screenTop and screenBottom, and we have an initialized method. The initialized method needs to get called to calculate the locations of the screenLeft, screenRight, and screenTop and screenBottom. There's some math here that is pretty straightforward. I'm not going to spend time working through it, but if you want to really understand how this happens, go ahead and work through this on your own. You'll see that I'm saving the lowerLeft and upperRightCorner of the screen in screen coordinates. Then using our favorite ScreenToWorldPoint methods to convert those to world coordinates and then just saving each boundary individually here at the end. I didn't show you in the editor, but ScreenUtils is not actually attached to the main camera but the GameInitializer script is, and the only thing the GameInitializer script does is called ScreenUtils.Initialize. You'll notice that I'm actually using the Awake method here, not the Start method. The Awake method gets called before the Start method gets called. When we discover we really need to care about that, we'll talk about it. We don't need to do it in this lecture, but we will talk about some scenarios where we need to use both the Awake method and the Start method to make sure our sequencing of processing happens properly. I've also changed the character script. The character scripts now has two fields, the colliderHalfWidth and the colliderHalfHeight. Let's talk about an example of the character leaving the screen on the left-hand side. The way we can discover that the character left the screen on the left-hand side is we can take the current transform.position.X of the character, and we can subtract half the collider width. So that's colliderHalfWidth here. That will give us the world location of the left-hand side of the character. If the left-hand side of the character is less than screenLeft, then we know that the character is partially outside of the screen on the left and we want to drag them back into the screen and bang him right up against the left-hand side of the screen. We'll see how to do that before we're done with this lecture. Remember in the previous lecture, I said, I knew we needed to keep the Start method, and here we need the Start method. What we do in the Start method is we get the BoxCollider2D that's attached to the character, and we put it into a local variable called collider. Then we take the horizontal component of the size of the collider. I'll tell you that the horizontal component of the size of the collider is the width of the collider. We divide by two, so that gives us half the collider width and we save it into that field. We do the same for the height. This actually saves us from having to divide by two on every frame of the game to calculate colliderHalfWidth and colliderHalfHeight. This is an efficiency thing to make it so we don't have to do those divisions all the time. We just do them once here and save the results into these two field. Update works exactly the same way it used to work, except that I now call a new clampInscreen method. In this method, we'll make sure we keep the character clamped in the screen. As you can see, the clampInscreen method doesn't do anything right now, but we'll now implement that method to actually implement the clamping. I know that what we're going to want to do is change components of the transform.position, either x or y if we need to actually move the character back into the screen. We'll start by saving the current position of the character into a local variable called position. We need to do this because we can't actually set transform.position.x or transform.position.y directly. We can set transform.position, but we can't set the properties of the transform.position. We need to save transform.position into this local variable. Before I forget, because sometimes I forget, I know at the very end, I need to set transform.position equal to position. Because any changes I make to this local variable don't actually change the characteristics of the GameObject the script is attached to, I need to do this to actually move that GameObject. Let's start by clamping horizontally. As I described earlier, the way we can check if the character is partially outside the screen on the left is we say, if position.x, which is the center of the character minus colliderHalfWidth. That gives us the left edge of the character. If that's less than ScreenUtils.ScreenLeft, then we know that the character is partially outside the screen on the left. I'll take this suggestion, even though it's not exactly correct because if we did this, then we've just centered the character on the left boundary of the screen, and we don't want to do that. We need to add colliderHalfWidth to make it so the left edge of the character is up against the left edge of the screen. If you need to use a piece of paper and a pencil to draw some pictures to see why this works this way, that's great, you should go ahead and do it. When I'm doing work like this, I regularly I'm sketching things out to make sure I'm getting it correct. This clamps horizontally on the left but not on the right. So, we'll do an else if position.x plus colliderHalfWidth is greater than ScreenUtils ScreenRight. If that Boolean expression is true, then we know our character is partially outside on the right. We will set position.x equal to ScreenUtils. ScreenRight, minus colliderHalfWidth. Then I'll take that suggestion. That will push the character so that it's right up against the right side of the screen. Now you'll notice I used an else if here, not an if. That's under the assumption that your character is not wider than the screen. If your character is wider than the screen, you have bigger problems here. But in general, the character will not be wider than the screen so, using an else-if here is appropriate. I'm going to clamp vertically as well. I'll just type that in and then we'll come back. Here's the code to clamp vertically. You'll notice I started here with an if, because I may need to clamp both horizontally and vertically if the character has left the screen at one of the corners. I want to make sure clamping works properly at the corners as well. I clamp horizontally and I clamp vertically but I might be clamping both. The logic here is very similar to what we did for clamping in the horizontally. The big idea is if our current y position plus colliderHalfHeight is greater than the top of the screen, we have to drag the character down a little bit and if position.y minus colliderHalfHeight is below the screen bottom, then we need to push the character up a little bit to be clamped against the bottom of the screen. That's all the code we need to write to do our clamping. I'll build. As a reminder, the main camera has the game initializer script attached to it. When I run my game, you can see the character is clamped on the top, left, right, and bottom, and it works in the corners as well. To recap, in this lecture, you learned how to clamp the character's position so it stays completely within the screen.