 Alright, welcome back to the top-down camera tutorial series brought to you by IndiePixel. Alright, so in this video, we are going to walk through the coding up of the main functionality of this particular camera, right? Alright, so what I want to do is jump over into Unity. Alright, so here we are inside of Unity, and we got our script ready to go. We've stubbed in all of our variables, and if we take a look at the code here, we've stubbed in all of our main methods. So all we need to do now is actually write the meat of this thing. So what do we want to do? Let's talk about this actually really quick. I always kind of like to think about what I'm going to do. So I know I want a camera that is a top-down camera. I want to be able to rotate it to a certain angle, so we basically follow it around at that particular angle, okay? So what we're going to do is we're going to get the target. Alright, first we're going to store that in a variable. It'll already be stored for us in the target variable, but then I want to find its forward vector. Alright, so the forward vector is the blue arrow here. If you're not familiar with some of the terms I'm using here, I'll try to make it as simple as possible. Alright, so that's the blue arrow that's always pointing forward, so for you to rotate this guy, and we go into local mode there, it's always pointing forward. So we can always get that forward direction, okay? So what you need to get that, we're going to get the position in world space of this particular tank, and then we're going to basically build a vector that uses that forward vector, but we're going to push it backwards, multiplied by the distance variable right here. And then we're going to add another vector to that particular vector, right? So we're going to draw a vector or build a vector that points out to the back here using this distance variable, okay? And then we're going to add another vector to that vector, alright? Using vector 3.up, multiplied by the height, and that, when you add those two together, what will happen is you'll get a vector that basically adds an angle to the tank directly in back of it like this. It'll be up here somewhere, and we're going to visualize all this stuff as we go along, so hopefully that will make more sense, but I wanted to talk through it first. So let's go and do that, okay? So the first thing that we want to do is we want to make sure that we have a target, because if we don't have a target, then we're going to get a whole bunch of null references, alright? So there we're checking for whether or not we have a target. We can also do something like this. You can say if not target, and then we just return, alright? I've seen it done both ways. So if you do that, then basically what happens whenever the update or start function try to fire this method and we don't have a target, it'll just exit out of the whole script and it won't do any of the code that's down here basically, alright? Now if we were to do it the other way, and say if we do have a target, then all your code would go in here, so I just wanted to show the two ways really. So let's do this way, it is a little cleaner. We also need a semicolon there, alrighty. So the first thing that we want to do is get that world position, okay? So let's create a vector three called world position, and we'll say this is the vector three dot forward, okay? Times the negative distance, so we want the m distance here, okay? And then we want to add the height, so we're going to say vector three dot up, alright? Times m height. And that will give us our first vector. So in order to view this, let's just make sure we didn't create any errors for ourselves, alright? So now, one thing I always like to do is have the ability to actually visualize what my vectors are doing when I'm adding these things up. So what we can do really quickly is say debug dot draw line, oray, you can do either or I'm going to use draw line in this case. And what we're going to do is say we're going to start from the target's position and we're going to go to the world position, alright? And then we want to give it a color, so I'm going to just give it a red for now just so I can really see it, alright? So let's take a look at that and see what we get. Now in order to see this particular vector, we actually have to hit play. So let's hit play, and there you can see our vector that we built. So what it's doing is it's actually taking the world z of the world forward and pushing it back by this distance value, okay? And then we're adding another vector together because you can add two vectors together to get a height. And that gives me a position right behind this particular tank, alright? Cool. Alright, so the next step, alright, let's make ourselves a little note here. So we're going to say build the world position vector, build world position vector, alright, going to try to be a good programmer and make myself notes, okay? So now what we want to do is we want to rotate that by our angle, right? Because I don't want the, let's hit play here, because I don't want the camera to always be behind the tank. I mean, maybe sometimes you do, but I want to give the user of this component some options of where they want to position the camera. Well, maybe I want it right here or maybe I want it right here without actually rotating the camera. We're going to do this all through code, you know, alright? So in order to rotate a vector, we have to build a quaternion, okay? Now don't be scared if that does scare you, it's totally fine. I'm going to try to make it as easy as possible, alright? So we're going to build our rotated vector, okay? And I need to spell right, alright. So what we're going to do is we're going to create a new vector called rotated vector. Rotated vector. And in order to make this rotated vector, we need to take the current vector that we have, this world position vector, okay? So we want to multiply it by a quaternion, okay? And a quaternion represents a rotation based off the z-axis or the forward axis of the object in question, basically. Alright, so what I'm going to do is say quaternion.angle-axis, alright? And I like to use angle-axis a lot because all I've got to do is provide it the float angle and then the axis I want to rotate on, so x, y, or z, right? So in this case what I'm going to do is just throw in the m-angle, okay? And then vector three dot up. And the reason why I want dot up, yeah, let's do that here, hold on one second, is because I want to rotate around the middle of the tank here, right? So I want to rotate around the y-axis, right here, okay? And we're getting an error because I haven't finished the line of code here. Alright, so then we want to multiply that by the world position. So we're going to say world position, like so. And now we can, let's copy this line of code right here. Let's draw another line over here, and this time we're going to display the rotated vector and color it green. Perfect, alright, let's let that compile and then we'll hit play, alright? Now we can see where we are at, boom. There we go, so as I rotate the vector, alright? So remember the red is the world position, so that's not first step, and then we rotate it by a quaternion. So, and we're rotating it around that y-axis. So that's basically how that works, alright? So I definitely do like the 45 degree angle. Makes it feel like one of those orthographic games, which is what I like. Alrighty, cool. So let's move on to the next step, and this actually is to make it move. So you'll notice that if I drive the tank around, okay, the vectors aren't following along. Those vectors are just stretching actually. And what we need to do is we actually, every frame, we have to add on the current position to those two vectors that we have, right? So in order to do that, it's really simple, alright? So let's move our position now, excuse me. Alright, so it's really, it's really simple. So what we want to do is we want to get the target position, okay? So, and then I just want to flatten it out in y, so that way we don't get any undulations as the tank itself goes up or down, okay? So I'm just going to call this the flat target position, okay? And we'll first assign this from the mTarget.position. And then to flatten it out, we just say .y is equal to zero. Now that means it'll always stay on the zero axis of the y direction, basically. Alright, we won't go up and down as we go over bumps or anything in our terrain. Alright, and then finally, I just want to build a final vector with all these things. I'm combined, so we're going to say final position is equal to the flat target position plus the rotated vector. Boom, and I hate it when I do that, I always do that. Because my finger's moving faster than my pinky finger can hit the shift key. Alright, so, and then finally, yeah, let's just do the final draw. So we're going to say debug.drawline. And I really didn't need to type it over again, but whatever, so we're going to do it again. And we want final position. And we'll color this one blue, just so we can identify each one. And after that, all we need to really do is just assign this final position to the transform position. Let's say this transforms position is equal to that final combined position that we did. Alright, so let's do that and take a look at what we got. Alright, I'm going to give the game view a little bit more space here. Let's hit play. And now, you'll notice that, well, we are actually, let me select this camera here. We are actually at the right position. Alright, and the camera is moving with the tank. And you can see now that we're updating the position of the combined vectors there. It's actually moving the camera around. But the problem is that we're not looking at the tank. Alright, everything else is working just fine. We're not looking at this tank. So, that's an easy fix. All we need to do is transform.lookat. So, say transform.lookat. I mean, there's tons of ways you can do this, but look at the quick and easy way to do that for sure. We want the m target dot position. Or you can use that flat target position too. Let's just do that. Alright, very cool. And now, we should be all set up. So, let's take a look. Boom. That's perfect. So now, we just need to really adjust the heights here. So, that's pretty good. I want to go out a little bit farther. Adjust the height here a little bit more. Boom. We now have a little camera. So, the last thing I really want to do before, I mean, you can leave it at that. But I want to kind of smooth it out too. We really don't need to be displaying all those vectors. They're really there just to help you out. So, what I do is I just comment these out, all the draw lines. Just comment all those guys. But I leave the code there just in case something happens and I want to show it again. You can write another function for all that stuff too, but this is the quick and easy way to do it. So, the last thing I want to do is actually smooth this out. So, instead of just directly assigning the final position to our transform position, let's actually use a smooth damp function. All right, so to do this, I'm going to need a private variable called private vector three. I'm just going to call this the ref velocity. And really, that's just to store the reference variable. You'll see here in a second. So, we're going to take advantage of the vector three dot smooth damp function. Okay. And you'll notice that it takes the current, the target, and then it has this ref velocity. It's storing the reference. So, I believe it's the delta or something like that, right? And then we have a smooth time. So, what I want to do is put in the current, which is transform position. Okay. And then the target is the final position because we want to try to get to that position. Okay. So, final position. We're going to say ref and then ref velocity. I'm storing it in that variable. And then we'll do it something like 0.5f. So, and we can also add a variable. So, we can say public, public float, smoothing speed. So, m smooth speed like that. So, I'll just initialize it to 0.5 and get rid of that dash there. That's not good. Alrighty. So, I'm going to copy that and we'll put that in place like so. Very cool. One quick note here. You don't have to necessarily be using these public, right? Because when you do this, you're basically allowing everyone to access the top-down camera class and change these variables from other parts of code if you want. So, there is another practice where we make all these private, right? And then we just do a serialized field on top of all these guys. I just don't do that for the videos here. I mean, I should probably, right? That's our practice because if I make these private or protected, right? I'll just leave it private for now. I'm not going to extend this in this particular series. Serialized field, right? By doing this, we encapsulate our scripts and protect them from any other script changing this particular thing. So, maybe we want to change, maybe we want to let other scripts change the height and the distance. We want to change the property then for that to just allow them to set and not get, basically. That all comes down to design. But anyways, I just wanted to cover that. You're going to see that a lot more in a more professional setting just because it's proper encapsulation of your scripts. Okay? Alrighty, so that is everything. So, that should smooth this out. Let's take a look now. Awesome. So, you notice it will take a little bit more time to get to the actual target. So, I'm going to set the height. I should show you guys in another series how to make it so that when you're editing these things at runtime like this, it saves. That's one thing that I hate because I always forget, right? I'm sure you guys have run into that as well. So, let's do like 75. That's good. I'm just going to copy these values and stop playing and hit paste values. Now we're good. Alright, so now you notice that we have a little bit of smoothing. And we can slow it down by adding more time. So, it takes more time for the camera to get to the position. Now you've got this interesting follow camera that has a long lag. So, it does actually let the tank kind of leave the center a little bit more. And I'll do another video on the adding like a lead to it, right? Those are always good or maybe adding or make the script take into account where the target is as well. So, it kind of fits the two. It would be kind of cool for this particular top-down. I really just wanted to show you like bare bones. This is what you do for top-down camera. Alrighty. So, that is the basic meat of our particular camera. One of the last things that I do like to do is draw some gizmos for this. So, I can select it really quickly. So, I'm going to do void on draw gizmos. And in here, what I want to do first is I want to check to see if we have a target. I know that I always have myself so I can easily draw a gizmos.drawSphere right away. So, I can just say transform.position. And we'll give it a radius of like 1.5 or something like that. So, if we have a target, I do want to draw a sphere at the target as well. So, I can see that. Okay. So, I need to do gizmos. Excuse me. gizmos.drawSphere. Alright. And we're going to do mtarget.position at 1.5. Alright. And then we want to draw a line. So, basically what I'm going to do is draw the line first. So, if you're not familiar with draw gizmos or undraw gizmos here or gizmos themselves, they do draw in order that you basically program them in. So, I want the line and the spheres. I want the spheres to be over the line basically. So, I'm going to draw the line first and then the sphere second, which will make the line look like it's underneath the spheres. It's not super important. It's just more like a stylistic choice that I make when I'm doing these things. So, I'm going to do a draw line. Alright. And we're going to go from transform.position down to the mtarget.position. Like so. Alright. Let's take a look at that. Very cool. Alrighty. And we have the little sphere. Now, I just want to give them a little bit of color. So, it allows you to select it. You can also come up here and just give it a icon. So, that way, when... That's weird that it's not doing it. It's probably because the gizmos... Huh. Anyways, that usually works. I'm going to move on here. So, basically, I'm going to give this a color. So, I'm going to say gizmos.color is equal to a new color. And the reason why I'm doing a new color is because I want green, but I want some opacity. So, I'm going to do an opacity of like 0.25f. Like so. There we go. Just kind of spruces it up a little bit. There we go. Alright. So, that's pretty much everything I wanted to do in this particular video. In the next video in this series, I'm going to make the tool for it so we can edit these properties inside of the scene view over here. So, I always like making these things. Alright, so I'll see you guys in the next video. Thanks so much.