‫Hello and welcome back.
‫Now we're ready to rotate the turret and we'd like to do this using the mouse.
‫And that hit location from the trace hit we've done in the previous video.
‫So as I'm moving my mouse cursor, the turret is rotating and facing the direction of the mouse cursor.
‫And even when I click in the viewport and begin to play, I can still move the mouse cursor around to
‫rotate the turret and set its direction.
‫This will allow me to aim when I have the capability of firing projectiles.
‫Okay.
‫So to achieve this, we need to find the direction that we want our turret to point in.
‫And once we've found that direction, then we can set the turret mesh rotation.
‫Now, in order to get the direction that we'd like the turret to point in, we need to do a little bit
‫of vector math.
‫What we're looking for is a vector from the tank turret to our trace hit location.
‫Now we can easily get the location of our tank or any of its components, such as the location of the
‫tank's turret.
‫We'll call this location, turret, location.
‫And we also know how we can get the location of the trace head.
‫We'll call this trace hit location.
‫What we're interested in is the vector from turret location to trace hit location.
‫We'll call this vector to target.
‫Now the vector math to get to target is actually quite simple.
‫To get a vector from a start point to an endpoint is always the endpoint minus the start point.
‫So if we take our trace, hit location and subtract the vector turret location, then the vector that
‫results from this is to target.
‫Now, once we have the two target direction vector, we want to convert that to a rotation so we can
‫set the rotation of the tank's turret.
‫And the vector type has a built in function called rotation.
‫So if we took our to target vector and called rotation on it, this would return an F rotator corresponding
‫to that direction.
‫Now we do need to keep something in mind.
‫The trace hit result is often going to be on the floor and the vector from the tank turret to the trace
‫hit result is not going to be parallel with the ground.
‫This means that if we set the tank's turret rotation to the rotator we get from that direction vector,
‫we might get something like this where the turret is angled down towards the ground, but we don't want
‫the tanks turret to rotate downward.
‫We want it to still point forward.
‫So this is the result that we want.
‫In other words, we only want to change the yea component of the tank's turret rotation.
‫So that way it's pointing in the correct direction but still remains parallel to the ground.
‫We've only changed its yaw, so let's hop back into VS code and create a function for rotating the tank
‫turret.
‫Now we're going to be rotating the turret on the tank, but we'd also like to rotate the turret on our
‫tower enemy and the tower is soon going to be created derived from base pon, which means if we create
‫a rotate turret function we can place it here in the base pong class.
‫So that way both the tank and the tower will inherit this function.
‫Since we plan on using it in both the tower and the tank, we can make this function protected.
‫So I'm going to add a protected section and any functions and variables we place in the protected section
‫will be accessible in these child classes, but not in any other classes.
‫So it's almost as restricted as private variables.
‫Now this function can return void.
‫I'm going to call this rotate turret.
‫And in order to rotate the turret, I'm going to need a sort of destination to look at.
‫This can be a f vector and we can call this look at target.
‫So the idea is if we have a function that we can pass in some sort of location in the world, then the
‫function should result in rotating the turret towards that location.
‫So let's go ahead and provide a function definition for rotate turret.
‫So here in base pawn CP just under the constructor, I'm going to implement rotate turret.
‫And of course I need the a base pawn class name with the scope resolution operator here.
‫So now that I have rotate turret, let's think about how we're going to implement this.
‫The first thing we need is that to target vector the vector from the turret component to the trace hit
‫result under the mouse cursor.
‫So this can be a local F vector called to target and we're going to set it equal to the result of some
‫vector math.
‫Remember, it's going to be the destination minus the starting point.
‫And the destination is look at target and the starting point is going to be the location of the tank's
‫turret, in other words, the location of turret mesh.
‫So we can say turret mesh and we can get the turret mesh location.
‫Now the way to get the world location of a component is with this function get component location.
‫It belongs to the use scene component class.
‫So all scene components have it.
‫So from the turret mesh we'll call get component location.
‫So look at target minus the turret mesh location gives us the vector from the turret mesh to the lookout
‫target.
‫Now, as I mentioned, we can get an EF rotator from to target using the F vectors rotation function.
‫So we're going to make an F rotator and we can call this look at rotation and we'll set this equal to
‫to target dot rotation.
‫That's a function call.
‫So now we have the rotator corresponding to this to target direction vector.
‫But the thing is we only care about the YA.
‫We don't want to change the pitch or role.
‫We only want to rotate the turret around the z axis and keep it parallel with the ground.
‫Now we can do this any number of ways.
‫For one, we can take look at rotation, pitch and zero that out.
‫In other words, set it equal to zero.
‫We can also take look at rotation dot role and zero that out as well.
‫Now after we've set pitch and roll to zero, we have the rotation we want, which is only the component.
‫This is one way to do it.
‫Another would be to use one of the F rotator constructor overloads.
‫If we said f rotator with parentheses and passed in some values such as zero point F for the first and
‫the pop up is telling me that that first input is the pitch.
‫And then for the ya we can use to target rotation.
‫Yeah.
‫And then for the role we could use zero dot F.
‫Now what this does is creates a new F rotator with zero for the pitch, zero for the role and the component
‫of the rotator returned by two target rotation.
‫So the value returned by this would give us the same result as what we did here with these three lines.
‫So since this is a little bit more compact and elegant, I think I'd rather use this so we can initialize
‫the look at rotation vector with the F rotator returned by calling the F rotator constructor like this.
‫So I'm going to remove this line down here.
‫And now we have look at rotation.
‫Now the last thing to do in this function is to set the rotation for the turret mash.
‫Now we can set the rotation for a given component using this function set world rotation again, it
‫belongs to use scene component.
‫And the reason we're using set word rotation rather than adding some sort of local rotation offset is
‫because we have a rotation in world space two target is a world space direction vector.
‫We're taking the turret mesh location in world space and subtracting the look at target location in
‫world space.
‫So this is a world space direction.
‫Therefore the look at rotation is a world space rotation.
‫So we're going to use set world rotation on the turret mesh.
‫So we'll say turret mesh, set world rotation and we're going to pass in look at rotation.
‫So now we have a function that can take any target in the world and turn the turret mesh to look at
‫it, but it won't rotate the mesh downwards.
‫It's only going to change its yaw, so it'll rotate in a way that a tank turret should rotate.
‫So we now have a function to rotate the turret.
‫I'm going to challenge you to call this function to set that turret rotation, call the rotate turret
‫function in the tank class.
‫This is a protected function.
‫So the tank class has access to it.
‫Now rotate turret takes an F vector, the look at target, you're going to use that impact point in
‫the F hit result from our line trace.
‫So I'm going to leave it up to you to find the correct place in code to call this function.
‫So pause the video and place the rotate turret function.
‫Call in the tank class.
‫Okay.
‫So we have our rotate turret function and we're ready to call it.
‫I'm going to go into tank up and here's my tick function inside the if check for player controller ref.
‫I have my hit result and after a get hit result under cursor has been called, the hit result will have
‫valid data.
‫In fact, we're using that hit result impact point and draw debug sphere.
‫Now since I don't need to draw the debug sphere anymore, I'm going to go ahead and delete that.
‫And instead I'm going to call our protected function rotate turret.
‫And for the look at target, I'm going to pass in hit result dot impact point.
‫So now every frame we're going to be rotating the turret towards that impact point from our hit result.
‫Now before I compile this, I'm no longer using draw debug helpers, so I'm going to go ahead and remove
‫that header file.
‫Okay.
‫Now I'm ready to compile.
‫Okay.
‫I'm back here in the editor.
‫Let's go ahead and hit play and check it out.
‫This is amazing.
‫I can still roll around.
‫I can move my mouse and the turret is rotating wherever I move my mouse cursor.
‫So this is awesome.
‫Okay, so before we wrap this up, I'd like to just address a couple of issues.
‫I want this to be nice and polished and looking great.
‫Now, the first issue happens when I move the mouse cursor close to the center of the tank and then
‫pass through it.
‫You'll see that at some point that rotation sort of snaps very rapidly.
‫And if we kind of move the mouse around in a haphazard manner, well, that doesn't look too great.
‫It's snapping.
‫We don't have smooth movement.
‫So that's one issue.
‫Now, the other issue is if I click and I roll around and I go up to the edge, I'll see that my turret
‫snaps in the other direction when I move my mouse cursor up.
‫So what's going on there?
‫Well, let's find out.
‫We'll go back to VS Code and I'd like to get my debug sphere back.
‫So back here in Tank, I'm going to go to the tick function right before rotate turret and once again
‫I'm going to call draw debug sphere.
‫Now for the world I'm passing in get world for the center I'm passing in hit result dot impact point
‫for the radius I'll use 25 dot F segments can be 12, color can be F color red persistent lines can
‫be false and lifetime can be negative one.
‫So same thing we did before.
‫So I'm going to save this notice.
‫I'm not adding the header file back up there and that's because debug helpers actually is included by
‫default, so we don't technically need it.
‫I'm just going to save jump back in the editor, do a live coding kickoff and press play.
‫So now I have my debug sphere.
‫So let's go up to the edge of the world and I'm going to move that mouse cursor up to where it falls
‫off into the abyss.
‫And that is where we have the problem.
‫You see, we don't have a hit result under the cursor when our cursor moves up there because there's
‫nothing there for us to get a hit result from.
‫Therefore, our impact point is not defined.
‫So what we need is something for that line trace to hit.
‫Now, Unreal Engine has lots of tools that we can use.
‫What I'm going to do is click the dropdown up here and open my place actor's panel and select this icon
‫that says volumes and get a blocking volume.
‫Here's blocking volume.
‫I'm going to drag one right on in.
‫So now I have this blocking volume.
‫Now by default, blocking volumes are supposed to be invisible.
‫If I go to the details panel for this and scroll down to collision, I see that it's Collision Presets
‫is Invisible Wall, which seems to suggest that it should block almost everything.
‫The only thing it's not blocking is the visibility channel and our line trace happens to be tracing
‫against the visibility channel.
‫Anything in our world that blocks the visibility channel will be hit by our line trace.
‫But this particular volume will not.
‫It's supposed to be invisible.
‫Well, we can go to the collision presets, open the dropdown and select custom.
‫This will allow us to change that so I can set the collision response to the visibility channel.
‫It's a block.
‫So now I have an invisible volume, but it's set to block the visibility channel, which means line
‫traces that trace against the visibility channel like ours are going to hit it.
‫So what I can do is I can take this blocking volume and scale it up.
‫I'll set it just beyond the wall.
‫In fact, I can place it right here at the bounds of the wall, and I'll bring it down a bit so that
‫it's sort of overlapping with the wall.
‫And that way we have this invisible barrier here, and I'm going to go ahead and scale it up in the
‫Y direction as well.
‫So I'll get that nice and big and position it in the middle here and give it a little bit of padding.
‫And I'm also going to scale it up in the Z direction.
‫So now it's nice and big and our line trace should hit it.
‫So let's test that theory.
‫Let's click in the viewport and go up to the wall.
‫And sure enough, I am hitting that blocking volume with my line trace and I don't have that issue where
‫my turret snaps to look at some undefined location.
‫It's probably looking towards the origin of the world because that impact point vector is all zeros.
‫Now if I go up to this wall, I have the same issue.
‫So we need these blocking volumes.
‫All around the perimeter of our level.
‫Now, that can be pretty easy.
‫All I need to do is duplicate this blocking volume.
‫Now I can change from perspective view to top orthographic view.
‫So I'm going to select top and scroll out with my mouse wheel and simply hold alt and duplicate this
‫wall and place one over here and I can hit E to go into rotate mode.
‫So I'm going to hold alt and rotate by 90 degrees.
‫That will give me a copy and then I'll hit double u and get my translation mode going and I'll move
‫it up here to this side and hold Alt and drag a copy down to that side.
‫So now we have four walls.
‫Now I can go from top view back to perspective and press play, and now I can go up to any of these
‫walls and it doesn't matter which wall I'm covered, so that looks great.
‫So that takes care of one of our problems.
‫But what about this other one?
‫If we move the mouse around close to our tank, we still have this sporadic behavior.
‫So I'd like to take care of that as well.
‫Now, the way I can take care of this is by interpolating that rotation.
‫So instead of setting this rotation value directly, we can use an interpolation function which will
‫essentially move that rotation towards the target that we provide in a smooth manner.
‫So let's see how that works.
‫Now, I'd like this interpolation to be in our rotate turret function so we can go back to base pawn
‫down to rotate turret, and instead of setting our world rotation for the turret to look at rotation,
‫we can set it equal to the value returned by an interpolation function.
‫So I'm going to delete, look at rotation and instead we are going to call a function on the F math
‫library called R inter two.
‫Now our in two is designed to handle interpolation for rotators.
‫Now its first input parameter is a const F rotator reference called current.
‫That's the current value of the thing that we're trying to change.
‫The thing we're trying to change is our turrets rotation and we can get that from our turret mesh.
‫So we'll say turret mesh and the function we want to use is get component rotation.
‫So it's a lot like get component location only it's getting the rotation.
‫Now the next input is an F rotator called Target.
‫That's the value.
‫We want this turret mesh rotation to interpret to to smoothly approach.
‫That's going to be our look at rotation.
‫So I'm going to say look at rotation.
‫The next input is Delta time.
‫So we know the importance of Delta time.
‫If we're moving things or rotating things, we want that movement to be independent of the frame rate.
‫So for that, we can get Delta time.
‫I can simply include gameplay statics and if you have a good memory, you'll remember that the include
‫is kismet slash gameplay statics.
‫So I'll get gameplay statics in here so I can access the static function, get world delta seconds and
‫remember this requires a world context object.
‫So I'm going to pass this into that.
‫And last, we need an internal speed.
‫The higher the value of internal speed, the faster we will interpolate towards the target.
‫So if I set this to a value of say, five F, then we'll interpolate fairly slowly.
‫Let's see how this looks now.
‫All of this is on a single line and it runs off the screen.
‫So what I'm going to do is place the input to set world rotation on its own line like this.
‫So just like that.
‫And then our interpreter, who has these four input parameters also running off the screen.
‫So I'm going to set them each on their own lines.
‫That way we can see all the inputs without having to scroll off the screen like that.
‫All right.
‫I'm going to go ahead and save that and kick off live coding.
‫And now if I press play and I move the mouse, notice that it's taking a while for that rotation to
‫happen.
‫That's because we're smoothly interpolating towards that target rotation.
‫Now, this is great.
‫That's exactly what I wanted.
‫No matter how I move my mouse, I'm never going to get that snappy jerky, sporadic movement.
‫Now, five is an awfully slow Internet speed, but we can change that.
‫We can make it a little bit faster.
‫I'm going to set this to 25, see how that looks, and I'll let you go ahead and decide on the value
‫that you like for your game.
‫So one more time, kicking off live coding and pressing play.
‫Now I have a pretty fast interpolation, but it's not snapping.
‫It's still quick, but it's not an instantaneous snap.
‫So as long as we're not doing something like this, well, we won't get that.
‫Crazy behavior.
‫And of course, if you want a slower rotation, you know how to do it now and we're done with draw debug
‫sphere, so I'll go ahead and remove that.
‫Okay.
‫So in summary, we've set the turret rotation and we're passing in a look at Target, which is an F
‫vector corresponding to a point in the world.
‫Right now we're just using the trace hit result.
‫Now we put this function in the base pong class and made it protected, which means that we were able
‫to inherit the function in the tank class.
‫And once we're ready to create a tower class based on base --, then that tower class is going to
‫inherit this rotate turret function and we can reuse it.
‫All we need to do is pass.
‫In a new look at Target, we'll work on creating a tower class derived from base -- in the lectures
‫to come.
‫I'll see you soon.