 Before we get into working with vectors, it would be nice for demonstration purposes if we could draw lines in the game world in a very simple way. Just doing so from code without having to add game objects and all that. And we can do that with the debug dot draw line method where you pass in a starting point and endpoint and then a color. So here we have two vector threes, A and B. And this first called the draw line is drawing from the origin. That's what this is. This is zero zero zero two point A two vector A and we're making that line green. And the second call we're also drawing from the origin but this time to be and we're making it red. So let's play the game. And you can see here the lines are being drawn but only in the scene view and that's because these calls to debug dot draw line. They're considered so-called gizmos. They are not really rendered elements of our game. They're there in our editor for visualization and editing purposes. And so that's why by default they're not showing up in the game view. But I can enable rendering of gizmos in the game view if I click this button. And so now they're showing up in the game view. It'll also be really nice if we can draw information and some basic controls on the screen rather than relying on the console for spitting out all information, which is a little clumsy in many cases. So we want to add some HUD elements and the way we do that in Unity there's actually an old system and the new system. The old system is called the GUI system aka the IM GUI system as an immediate mode system. This is legacy. It's kept around for compatibility with older games. But it's also what is used by the Unity editor itself when it draws the little windows and elements of the editor. And in fact if you want to extend the editor you can do so and when you do you use this old API to create those interface elements. Aside from those cases it's still sometimes nice to use this old IM GUI system for quick and dirty prototyping, for putting debug info on the screen and basic controls on the screen like say a button, but we don't really care how it looks like or if it's positioned precisely in the right spot. The old system is nice for this because we can very quickly do so with just a couple lines of code. We can put an individual element on screen. For more complex stuff and for things that we want to make look good you want to use the new system, which has more options for layouts, for styling, and also I've seen claims that it's more efficient, that this old system had some efficiency issues. But the way you use this new system is you create game objects with certain components, but particularly for prototyping and quick debugging purposes it's often more convenient to add these elements from code. And so here's how we can use the old IM GUI system. There's a special method in our scripts called on GUI. And this is a method that's called at least once per frame, though I think in some cases it can be called multiple times per frame. I'm not sure exactly why, but I know that's the case. Anyway, in the method we're calling static methods of GUI such as label here to create a text label, a button to create a button that we can click, text field to create a text field where we can enter text, and a box, which is just like label, but by default it has a gray 50% transparent background. And these methods all follow a pattern. The first argument is a rect argument, rect is in rectangle, it's specifying the balance of where the element is going to be rendered. So here, the first two coordinates, that's the x, y coordinates in screen pixels of the top left of where your element is going to be. So here 10, 10, that means the top left of our label is 10 pixels from the left of the screen and 10 pixels down from the top of the screen. And then the width is 100 pixels wide and the height is 20 pixels tall. Here for the button, it's 10 pixels from the left of the screen, 70 pixels down, 50 pixels wide and 30 pixels tall. The second argument to these methods is the content we want to render in the box. In all these cases, it's just a string, but there are other kinds of content. You can nest elements within each other, like say you could have buttons and text fields inside your boxes and things of that nature. But for our purposes, we just want to render some strings. And you'll notice that both button and text field are returning values. Label box returned nothing, but button will return true if the button you're creating has been clicked. And this is a little head scratching because we're specifying that the button exists every frame. Every frame we're recreating the thing, a new as if it didn't exist before. And yet the IAM GUI system seems to somehow retain information about what elements have existed before and what the user is doing with the screen, like say where they're clicking and if there are elements that require keyboard focus like text fields, where that keyboard focus is going to be. So there's a little bit of magic I don't entirely understand about this IAM GUI system because it's not really truly immediate. An immediate mode GUI system is one where the API doesn't retain anything about what our UI looks like from frame to frame. That's up to us to keep track of the state from frame to frame. That's why every called on GUI, which is called at least once a frame, we're effectively recreating the UI each time. And yet somehow it's registering that like say this button has been clicked in the same frame where it's being created and even more mysterious actually down here the text field text fields have keyboard focus. So in one frame you click the thing to give it keyboard focus. But then, but then I think as long as you keep creating that same text field the subsequent frames that somehow like keeping track of oh that thing still has a keyboard focus so that when you type this is the string here we're passing in which is this private field that's starting out starter text. But then each called on GUI recreating text field setting the string that we see in the text field and then text field returns the string whether or not it's been modified. So in most frames the return string here will be the same as the one we pass in but then in frames where the user has previously given the text field focus and they start typing on the keyboard they hit letters and spaces and backspaces and so forth. The return string will then reflect that input it will reflect those changes. So it's a little funny here because that part of the state we're keeping track of that ourselves. The GUI system is not keeping track of what text is in the text field but then the fact that the text field has keyboard focus somehow the system keeps track of that. I don't know exactly what's happening. By the way here the argument 25 that's just the max length this text field lets you enter. So the return string will be at most 25 characters long. Also note down here for the box the coordinate we specified for the X if you want to position something relative to the right side of the screen we can use screen.width to get the width of our game view and then subtract 200 from that and effectively now this box is positioned with its top left corner 200 pixels from the right edge of the game view. So anyway this is called at least once per frame and each time these method calls are putting these elements on the screen. So if we come here play the game and as you can see the UI elements don't show up in the scene view they only show up in the game and over here this is our label this is our button here I can click it and every time I do it's printed out in the console click the button with text because in our code we're checking what button returns and every time we click the button the next call to the GUI button here will return true and so that's why this is printed out. And then we have our text field down here I put keyboard focus on it and I'm just going to edit the text whatever I want and in our code each time I change the text in the text field that is what's being returned here and assigned to the text field of our class. And lastly the box here as I said is positioned 200 pixels from the right of the screen so as I change the width of our game notice it's just staying 200 pixels from the right of the screen. Anyway so now we can put some quick and dirty GUI elements on our screen there are ways in this old system to do more sophisticated layouts that is positioning of the elements relative to each other and relative to the screen and so forth you can also change the styling like say for our box if we wanted to change what color this background is or whether the corners are rounded or what the border color is etc and the fonts inside and their sizes and their colors we can do all that. If you're interested it's described here in the manual under UI and immediate mode GUI all this other stuff is the new system the canvas based system we'll talk about later in more detail but for now all we care about is that we can put some basic elements on the screen and that'll be handy when demonstrating other features. The vector two type as we've discussed is a struct consisting of simply an X value and a Y value two floats this struct has a number of interesting properties and methods which we're going to enumerate here in a minute but then we have the vector three struct which of course adds in a third float the Z component and this vector three class has all the same properties and methods but then it has a few things in addition and I'm going to briefly walk you through this as well though I don't want to really go deep in any math here some things that are kind of confusing later on we'll be going into more detail about how these methods and properties might be useful in games various ways they can be applied but there's a series of videos on YouTube that I recommend called math for game developers that starts out covering vectors and all these things we can do with them there's also a bunch of other topics matrices, quaternions and various other math stuff useful in games so that's a very useful resource but for now I'm just going to enumerate vector two and vector three classes first off with vector two we have these static properties right, left, up, down, one and zero and these are just vector two values which you might commonly use such as the unit vector pointing in the right word direction that is assuming you're facing down the Z axis in the positive direction the X axis runs off to the right so the right unit vector would have the coordinates one and zero and the left unit vector would have the coordinates negative one and zero up would be zero one down would be zero negative one and then one that's not a unit vector because the magnitude is not one but it's just both components are one and then there's zero which is just both components are zero so sometimes it's just not a short hand rather than having to write either of these I understand that the code won't be any more efficient either way whether you use these properties or not is really just a matter of style and then lastly we have positive infinity where both components are the special float value representing positive infinity and negative infinity where both float components are the special float value representing negative infinity and then getting into the methods here assume for all these examples that we have two vector two values one called A one called B and first off there's an instance method called equals where it returns true if your A and B are exactly equal so it's equivalent to just doing this doing a quality test between their X components and in that with a quality test between their Y components exactly the same thing but then the quality operator is overloaded for vector two such that it returns true even in some cases where A and B are not exactly equal there's a little bit of slough where if their difference is less than one E negative five that's one over ten thousand I believe yeah so if it's a very small difference you still get back true otherwise it'll be false and then the plus operator returns a vector where the X components have been added together to produce the new X component and the Y components have been added together to produce the new Y component and the way the plus override method is defined is it's commutative so A plus B returns the same thing as B plus A same result and then we have subtraction which is same deal except of course we're subtracting rather than adding but of course keep in mind subtraction is not commutative so it matters whether we're subtracting B from A or A from B the order changes the result we get and then we can also use the multiplication operator but not between two vectors one of them is a scalar value just an ordinary number value and what this does is it produces a new vector where the X component is produced by multiplying the X component of the vector times the scalar and same deal for the Y component and this is commutative so A times 5 is the same as 5 times A likewise for the division operator the other operator is just a number it's a scalar it's not a vector so this here is dividing the respective components by 5 the difference though is that this operator is defined only in one direction so if we try divide a number by a vector there's no defined method and so this is just a compiler the scale method does actually let us multiply two vectors together just like we add them and subtract them so here when we scale A and B we get the X component by multiplying the two X components together and we get the new Y component by multiplying the two Y components together and then we have a few instance properties which are read only such as getting the magnitude of the vector that is the length or the square magnitude where it's the length multiplied by itself which is useful in some cases because the way magnitude is computed is that it's actually cheaper to get the square magnitude rather than the actual magnitude because it involves the Pythagorean theorem and that requires getting the square root square roots are expensive operations anyway sometimes you want the square magnitude because if you're just comparing the two lengths of two vectors and you just care about the relative length you probably then would just use the square magnitude because it's cheaper to get than the actual magnitude also we can get the normal of our vector which is the unit vector that points in the same direction unit vector meaning it has a length of one so we have some vector points in some direction it has some magnitude which is not necessarily one but the normalized property returns is a vector pointing in the same direction but having a length of one and then a bit confusingly there's also the normalized method which doesn't return a new vector it actually mutates it so property returns the normal vector of A which takes A into its normal vector lastly here the vector 2 type also has about a dozen static methods we can use including distance which takes to vector 2's A and B and this is the same as subtracting B from A and getting the length of that vector when you subtract vector B from A you're getting a vector that effectively represents the direction and distance you would have to travel to get from B to A and so if we just want the distance between two points we get the magnitude of this vector the clamp magnitude method oops that really shouldn't say A not X we have some vector 2 called A and we want to get a vector which points in the same direction but if our vector exceeds the specified length here we want to get the vector pointing in the same direction but which has that length so say if A here has a length of 10 we'll get back here a vector pointing in the same direction but which has a length of 5 on the other hand if the length of 2 to A, if the length of A were already less than 5 we would just get back the same values A the max method takes two vectors A and B and returns a vector where the X component is the larger of the two X components and the Y component is the larger of the two Y components and likewise the min method returns a vector where the X component is the smaller of the two X components and the Y component is the smaller of the two Y components off the top of my head I can't imagine that it's identical but I'm sure there are cases where it comes up and next we have the static angle method which returns the angle between the two vectors and the angle returned is expressed in terms of degrees and it's the absolute angle so the sign is always positive and because it's the absolute angle it doesn't matter the order of the vectors if it's from A to B or B to A we get the same angle regardless whereas the signed angle method returns the angle and degrees between the two vectors but it's signed so it matters if we're getting the angle from A to B as here or the angle from B to A next we have the dot method as in finding the dot product and the dot product is an operation which is defined as multiplying the respective X components together and multiplying the respective Y components together but then we sum those two products together so we're getting back a single value a scalar value not a vector so that's how the operation is defined the interesting question is why is this useful well we can prove that the dot product of A and B is equal to the magnitude of A multiplied by the magnitude of B multiplied by the cosine of the angle between them and in fact this equation is the basis for how we compute the angle between two vectors which we won't go into here but understand that's how it's done and also be clear dot product is commutative as you can see here to get the same result moving on there is the LERP method LERP meaning linearly interpolate and that is we have two vectors which effectively represent points in space right there's a ambiguity between a vector of whether it's a point in space or it's a line from the origin towards that point it's kind of both at once anyway thinking of our vectors as being points in space something you would often want to do particularly in games is find the points in between some percentage of the way from A to B and that's what LERP does this here is going to return the point which is on the line segment from A to B but 40% of the way from A towards B if this were 0.5 it would be half way between them if it was 0% the vector returned would equal A if this value were 1 that's 100% of the way to B so the value we get back would be equal to B and then we have a variation LERP unclamped which is exactly the same but it doesn't clamp this value in the range of 0 to 1 so 2.4 effectively represents 240% of the way from A to B so we've gone past B twice over and then another 40% also could even be negative so you can start at A and move away from B you can go in the opposite direction if this value is negative then we have move towards which is similar we're starting at A and we want to find a point on the line segment towards B but instead of specifying the percentage of how far between them we want to go we specify how far we want to go in absolute distance so assuming here that the distance from A to B is 10 units this call is going to return a vector representing the point on the line segment from A to B that's 4 units away from A we've traveled 4 units from A towards B if though the distance from A to B is smaller than the value we specify here then the value we get back is just going to be B we're traveling from A towards B but we're never going to overshoot so in this case say if the distance from A to B is 3 units long well 4 overshoots that but we wouldn't overshoot instead we just get back a vector which is the same as B then we have the most complicated method to use called smooth damp which serves a similar purpose it returns a point on the line segment between A and B and the velocity we want to travel from A towards B we specify a time value which is in seconds of how long we want to take to reach the target to reach B we can also clamp the speed we're going to travel we can specify a max speed which defaults to infinity so effectively there is no max speed and lastly we're specifying for this one call what is the unit of time elapsed how long are we traveling so it's how fast we're traveling by the way is a special named parameter where you can emit it and it'll default to time.delta time so if you call it an update it'll just be whatever the delta time is for that update but otherwise you can specify it explicitly if you want but the weird thing here is this time to target this doesn't have any influence on the vector returned but velocity here is a special kind of parameter called the rough parameter which in C sharp means that the value passed in it's actually passed by reference and so it can be modified so smooth amp yes it's returning to new vector 2 but it's also modifying your velocity and the value it sets your velocity to is dependent on the time to target the method estimates given how much you're traveling here in this one operation in this one call given the remaining distance what velocity would you need to be traveling at to reach the end target in this specified time so this one's quite complicated it's a little involved but it can sometimes be quite useful because it's a fairly common thing we want to simulate an object moving from one point to another under acceleration lastly for vector 2 we have the reflect method which returns a vector with the magnitude of a the same magnitude but its direction is as if a has been bounced off a surface or in two dimensions I should say a line we don't have surfaces in two dimensions we have lines so what line though are we bouncing a off of well it's a line defined by this vector b where b is its normal and b must be a unit vector it must be normalized otherwise you don't get correct results so make sure it's normalized and also be clear this is a little strange but we don't care where the surface is positioned in space all that matters is its slope because it's the slope that determines the direction of the return vector and again the magnitude of the return vector is always equal to a's magnitude here's an illustration of how the reflect method works we're creating this vector a and b and then reflecting a off of b being sure to normalize b because it's expecting a normalized vector otherwise you get an incorrect result so we now have these three vectors and we want to draw them out first we make a green then we make b red and the reflection vector we make magenta so let's see that in action and before I hit play here we're going to want to see the x y axis dead on and we can do that by messing with these buttons here and I also click the button in the center that switches us to an orthogonal projection it'll look like a blueprint cross section of the x y axis anyway so hit play here and I'll hit shift enter to maximize the window okay so green here is the vector a this little green sphere is just illustrating the origin I also put that in the scene and the red line is our vector b this gets normalized so you have a vector with the same direction but with a length of one and that is used to describe a surface a line I should say we're in two dimensions so I should say a line that runs perpendicular to this normal so it runs like this that is the slope of the line and so now imagine that our vector a is hitting a line with that slope at this point so the way the line is described it doesn't really have a position it just has a slope so it's at this point where the contact is made and we bounce off at an inverse angle and that would be like shooting it off in this direction because the slope is like here it slanted this way so we would shoot off this way as you see here the magenta vector it has the same magnitude as our vector a and it has the direction of the inverse angle and to make this clearer here I'm going to come back and uncomment this line where we're drawing the reflect vector but the starting end point are offset by a so it'll draw starting from the end point of the green line so I'm going to use this code switch back wait for the code to recompile and there it is this is the same vector just drawn starting from this position rather than from the origin as you can see if the slope looked like this this is bouncing off at the inverse angle