3rd Person Shooter Controller with Cinemachine & Input System - Unity Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today i'll be showing you how to make a third-person shooter controller using cinemachine and the new input system in unity so you can see we can move around and when we look in another direction our character will rotate to that direction and we can shoot and the bullet will move towards that position in the center of the screen and then when we zoom in you can see that our reticle has changed and we can get a more accurate aiming with less movement and of course you can adjust these settings so it sways less and in the next video i'll be going over adding animations to this character from miximo which if you don't know they have all these free animations and characters that we can use and we'll be applying them to this game and i'll also be going over the animation rigging package so that if we look up for example the upper body will look up so the gun will aim upwards and it'll be more accurate all right so let's get started so once you have your project loaded the first two things that we're going to need are the packages so the input system and cinemachine so go to window package manager then go to up here packages unity registry and scroll down until you find cinemachine and let's install that and let's also download this cinemachine example scenes because they have a third person sample and we're going to be using that to make ours so we don't have to reinvent the wheel and lastly we need the input system of course so just click install here this is the 1.0.2 version if you want you can go to advanced advanced project settings and you can enable preview packages here i understand and when you open it up it'll show you all the preview packages if you want to download the more recent versions so i'm just going to download the newest one and here just click yes to restart the editor alright now that you got that set up let's just make a simple floor here 3d object cube and i'm just going to increase the size here to 100 on the x and 100 on the zed so we have our floor and i'm also going to right click and create a 3d object capsule and this is going to be our player and you can just bring the player down to the floor and quickly i'm going to go into the assets and create a new folder for our materials just so we can assign the floor and the player an interesting material so you can right click and create a new material let's just call it floor and i'm just going to paint it kind of grayish for now let's assign it there and we can do the same thing for our player right click create material and i'm just going to name it player and assign it a red color so we can easily distinguish it and you can just click it and drag it on to your player as we did for the floor another thing i want to do is add in another 3d game object in front of the player just so i can see what its forward direction is so you can see our player's forward direction is the blue arrow and i'm just going to make this small cube right here just so i can see kind of like some vr glasses and i'm just going to assign the floor material to it because why not i'm just going to call that face so i just clicked it f2 and face and so that's our basic player for now now let's add in some movement so in your assets folder right click and create another folder and let's call that scripts and when you're inside right click and create a new input action and let's call it player controls action maps are a set of controls a grouping of controls so let's just create an action map for our player for example you can have player ground and then you can have another one for player swimming if you have different controls for each situation and our actions are the actual controls so there's a couple of actions we want to make we want to make a move a jump a look an aim and a shoot action so you can click the first one press f2 rename it to move then for the action type select value control type vector2 since this is going to be with our wasd keys or arrow keys and we're going to be moving in two dimensions the x and the z axis and for our binding we can actually just right click and cut this one and instead let's add up here a up down left and right composite and let's call this wasd if you're gonna use the wasd keys and so now we have a 2d composite up down left and right and then we'll assign our keys to correspond with what we want to be up down left or right so for our up we want that to be w so click on this path here click listen and then click w on your keyboard and now you've selected w and let's do the same with the other ones path listen s that's going to be our down in our case up is going to be going forwards down is going to be going backwards left path listen a and right path listen d so we're going to be using the wasd keys and it's going to return a vector 2. up and down is going to be our y so if we're going forwards we're pressing w it's going to return 1. if we're going backwards and we're pressing s it's going to return negative one on the y and vice versa for left and right this will return one if we're moving right on the x for that vector two and if we're moving left it will return negative one on the x or the vector two all right now that we have that done let's make a similar one for look so our look is also going to be a vector 2 value control type vector 2 and that's because we're going to be moving our mouse around and it moves on the x and the y axis so for this one luckily they have a path already we can use go to mouse and just select delta delta is the change in position between our current frame and the previous frame and so it's used to get the direction in which we're moving in because the difference between the current position and the previous position gives us the direction and that's our delta and we'll be using that for our cinemachine look next we'll need our jump action and we can leave that as a button for the no binding just click listen and spacebar and of course you can customize these to your liking the other action we need is aiming so aiming is going to be our right clicking on the mouse so that's a button go to path mouse and then let's select right button mouse and finally let's do a shoot action it's going to be a button as well and for our path let's just click the left button on the mouse alright now that you have all of your actions set up click save asset and then exit out of that now let's make a player controller so for this i'm actually going to be using the player input component for the new input system so in your player you can just add a component here player input and so this is unity's way of making it easy for you to access the values in your input action asset and the reason i'm using this is because usually i do this generate c-sharp class but unfortunately if you want to rebind your keys if you want to let the player rebind their keys in game this isn't really supported if you do it this way because this generates a new script and if you're playing the game you can't really alter the generated script so they actually recommend to use the player input component which can change these values dynamically during the game so we can just drag in our input action asset here and it selects our default map as player and we can just assign our camera here for our current player and now that we have this player input component let's actually create a new c-sharp script called playercontroller and this will control the movement of the player all right and so you know how i like to take shortcuts so in google just search up character controller click on the first link if you don't see it just search unity character controller and we can go down to the move public method and so they have a script that we will just be copying because why not and let's just replace our script there we can remove these two using statements since we won't be using them and let's just replace this class name with playercontroller so what this does is it uses unity's character controller component to move the character so in our update function which runs every frame you'll see that it's doing a grounded check is the controller grounded if it's grounded and the velocity on the y direction is less than zero then let's just set it to zero since we're on the ground anyways then here it's getting the input with the old input system which we want to replace and then it's moving the controller based on that and the speed this rotates the character depending on their movement and this is the jump code so if it's jumping and it's grounded apply a velocity using the physics equation and then move the controller with added gravity so let's change this to use the new input system so first we want to scroll up and do using unity engine dot input system then here we want to add in a require component and this is to make sure that when we add this script to a game object it'll add these components in for us if it doesn't have it already so only put this if you need to have the component added so require component type of character controller so we need a character controller and let's add one type of player input all right and then one thing i like to do is these values we can move these upwards and if we want to change these in the inspector let's just add a serialized field here so we can change them while in play mode and test out some values then we want to actually access our controls from the player input component and there's a way to do that so first we need a reference to our player input component so private player input player input then in the start do player input equals get component player input and then actually here in the controller since this component component's already going to be added with this required component let's just do get component character controller instead all right and so the way you can access the controls is as so so player input dot actions so these are our set of controls and then we can index into it with a string so let's say we want our move action so this will return our move action and if we wanted to we could read its value and it's a vector 2 and this would return the current move value however since i don't really want to be using the string all the time because i might make a mistake i might misspell it like that we only want to do it one time so let's actually cache this value so up here let's do a private input action move action and let's just duplicate that a couple times one two three let's do look action we also have a jump action and actually let's just start with those three for now so let's take the move action and equal it to our player input actions move now let's copy that two more times look action here and let's put look here and finally let's replace this one with jump and jump action all right so here in the movement let's do vector 2 input equals move action dot read value vector 2. so now we have our input with the new input system and let's just replace this move vector with the new input systems so input dot x and input dot y and let's actually remove this rotation code because we won't be using it and for the jump here we can do jump action dot trigger so this will return true on the frame that this jump was pressed it actually made a small mistake we don't need this look action so we can just remove that for now all right so we've replaced it with the new input system so let's minimize that and add it to our player so in the player here let's add in a component player controller script and you'll see that it automatically added our character controller for us which is really nice and it has these values here one thing we want to change is the min move distance to zero if you don't change it to that it'll have some problems jumping that basically means that if the character moves less than that distance it will not move at all so if you're just kind of standing still and trying to jump it might not jump at times so just make sure to set that to zero right so if we click play you'll see that now we can move around when we press the wsd keys and when we press spacebar it will jump however you see that the camera is not following the player and there's also no sort of character rotation whatsoever so now let's actually do the interesting part which is adding the third person camera perspective to the player so for that let's go to our assets folder then we're going to go to samples send a machine 2.6.4 or whatever number cinemachine scenes third person and third person with aim mode so here's their sample package for third person controller and if we just click play and see what it's like you see that there is an error because we're trying to use the old input system class for movement in this sample because they don't implement the new input system in their samples for some reason so just for now to show you what it's like i'm just going to go to edit project settings then i'm going to go to player and i'm just going to change the active input handling to both although i do not recommend this do not do this i just want to show you what the sample is like all right and now if we click play on the sample you'll see that we have this nice third person controller here it's a little fast unfortunately but you see that it can kind of move around for some reason it's vibrating don't ask me why and if we press control it kind of zooms in the camera but what we want is basically to copy this controller virtual camera that they've already made since they've done all the work for us so in your assets right click and create a new folder called prefabs double click that folder and let's drag in their normal third person machine camera along with their aim camera so you can see that it won't let us add this game object to our prefabs for some reason it always happens so what i do is just click the normal one ctrl d to duplicate it go to the aim right click on the cinemachine virtual camera copy component go to the normal one right click paste component values so it just pastes literally all the values that we need and now let's just drag it there and let's just select original prefab here let's rename that f2 aim cinemachine and the other one to third person cinema machine alright so now that we have those nice values let's go back to our scene under the scenes folder alright so then open up your prefabs and drag in the third person cinemachine camera so what cinemachine does it basically is a virtual camera and it has a set of defined behaviors that controls the main camera and so the main camera will have to add in a cinemachine brain component because it's kind of like cinemachine is injecting its behavior or its brain into the main camera and you'll see that there's some settings here that will be changing soon such as the default blend which is how it switches between cameras so make sure your main camera has this back to our cinemachine virtual camera which is the one defining the set of behaviors we first want to assign a follow and look at properties so this is what the camera is going to be following so obviously we want to make it follow our player so drag your player into the follow property here and i'm just going to put the game to the side so i can kind of see how it's looking and then we'll also want it to look at the player so drag in the player to the look at component and so you might be wondering if you're familiar with cinemachine why we're using this virtual camera instead of the free look camera which i've used in previous videos and it's because this camera felt more snappy and with shooters with third person shooters you want your camera to feel more snappy and quick if you have this in a machine free look camera you'll see that there's three rigs around the player and the camera kind of moves along those three rigs and it can be kind of hard to get right at times the correct angles and it kind of looks weird so let's not do that so instead we're going with the virtual camera which is the main one and there's two main aspects there's the body and the aim so the body is how the camera moves and the aim is how the camera looks so the follow is the movement and the look at is the aiming in this case it's aiming towards the player so there's a couple options here and we're going with framing transposer because there's not a lot of settings that we can use here while the framing transposer has a lot more settings that we can use like more damping the screen x the screen y deadzone soft zone and we don't want to do an orbit we don't want to do a hard lock which kind of limits its movement and the track dolly is more for a kind of cinematic experience then there's a transposer which is kind of the same thing except you'll see that it has a lot of less options that we can use the framing transposer has a lot more options and settings all right and then for the aiming we're going to be using point of view pov so it's kind of as if we're in the point of view of the player and if you like here's a list of the aim properties and what each one does so the pov rotates the virtual camera based on the user input which obviously we want to happen the composer and group composer keeps the targets in the frame this one sets the camera's rotation to the same rotation of the follow target and the hard look at keeps the target at the center of the screen at all times but we want to be more liberal in our movement with the camera so select pov for this one another thing i want to mention is that it also has some nice noise here which adds a sway to the camera so for example if we just click play right now you'll see that it's freaking horrible so i'm just going to disable the cinemachine collider for now because it kind of freaks out but you see that if we're just staring the camera kind of sways with the wind which is nice a lot of games do this to make you feel like you're more in the environment and you can see we can look around the player but our player is kind of down there so we're gonna have to adjust our settings a bit so i'm gonna go over the settings that i found the most useful so look ahead is cinemachine kind of predicting based on the player movement where the camera should be moving and looking ahead to that area this is the offset from the object damping kind of softens the movement of the camera so it's more smooth instead of it just being quick screen x and screen y we'll want to change this so i'm just going to make the screen x a little lower and it basically moves the camera with an offset and i found 0.25 to be a pretty good value then for the screen y i'm gonna also decrease that to maybe point one seven so the character is kind of on this side of the screen you can also put the player on this side on the right one camera distance is how far the camera is from the player so i want it to be a little further out and dead zone is basically where you don't want the camera to go so you can actually click game window guides so let's actually change our aim a little bit here so this uses the old input system mouse y and mouse x so let's actually replace it with the new input system so add a input provider component it's in a machine input provider and this basically overrides the mouse x and mouse y so you'll see that they disappeared from the aim section and now for the x y axis let's just click this button here and select our player look input action and so this is our delta mouse movement in the x and y axis and it will replace these values and so one thing i want to mention here is in the speed here i found point zero three to be good and in the horizontal one i found point zero eight to be good and so this one uses input value gain which basically aims the camera depending on how fast your mouse is moving so it's entirely dependent on how fast your mouse is moving or your delta instead of using this which kind of smooths out the movement more with the delta values and more damping and so you can actually change how the player looks by changing the vertical axis values so you can see that if we move it down it'll aim it more downwards and we can move our horizontal axis so it looks more towards the center of the screen all right so now if we click play we can actually look up look down and we can look around the player pretty cool and you'll see that there's actually some sway but it seems a little too much so let's scroll down to the noise and you can probably decrease this a little bit maybe 0.7 instead so it doesn't look around so much all right and so you see even if we move our camera the player does not rotate in the direction we're moving in so let's quickly change that go to your player controller script and here we'll want to take into account the camera direction so what direction the camera is looking at so that we can move in that direction and for that we'll need a reference to our camera transform so private transform camera transform in the start then we can do camera transform equals camera.main dot transform so we don't want to be calling camera main all the time for no reason so we want to do two things first we want the player to move in relation to the camera so when the player presses w we want the player to move forwards and that forwards is going to be in the direction of our camera so if we're looking to the left and we press forwards then we want our player to start moving to the left similar to how first person controllers do it so to do that we have to take into account the camera transform in our move vector here and to do that we can do move equals move dot x times camera transform dot right and let's just do a normalized vector which returns the vector with a magnitude of one so we can just get the direction we don't really care about the value and then we're also going to add in move.z times camera transform dot forward dot normalized so what this is doing is basically taking into account the camera direction when we're moving so when we move to the right or the left it'll take into account what direction the camera's right and left is and it'll multiply it and we're just adding in the same thing but for the forwards so when we move forwards we press w or we move backwards press s then we times it by the forward vector of the camera so that we move in relation to the camera and here just make sure to set move.y equals to zero if not it'll look kind of funky jumping all over the place we only really care about the x and the y and if you times it in here it might put in an extra y value that we don't need all right so just to test it out you'll see that once we start to look at that way then we'll move forwards in that direction even if our character is not rotating and if we press a to move left you can see that we are now moving left in relation to the camera all right now let's rotate our character depending on where we're aiming so i'm just going to add a comment rotate towards camera direction so for that we need the rotation of our camera so let's get that so float target angle camera transform dot euler angles dot y so this returns the camera's current y rotation in an easy to digest format so euler angles is a vector three this is a quaternion it converts it into a vector three and we're getting that y because we want to rotate it around the y-axis because in the player for example if you change the rotation code it rotates around that axis which is the green one so it rotates around it so we have that angle now we need a new rotation for our player so quaternion rotation equals and so now let's convert this to a quaternion so quaternion.euler we don't want anything for the x let's just type in our target angle here and then nothing for these ed so really you can just actually copy this and paste it here if you wanted to and all this is doing is creating a quaternion for our player to rotate in and so now we can change the rotation transform.rotation equals and instead of just setting it directly you can do kind of a lerp so quaternion.lerp you can also do slurp which is spherically interpolate while this is linearly interpolate which makes it more smooth so to lerp we have to put our beginning from the current rotation we're going towards the target rotation and then let's do it at a speed rotation speed times time dot delta time now let's set our rotation speed up here serialize field private float rotation speed and i'm just going to set it to 0.8 f right just save that and now if we click play we can see that once we look around the player starts to move in the direction that we're aiming it although it does it a little slowly so maybe we can put it to two and it'll be a little faster five i like five better alright so i'm actually gonna set the default value here and the rotation speed to 5 and i'm just gonna set it there as well all right so now that we have the main third person to the machine done let's click that one press ctrl d and just rename it to aim cinemachine so f2 to rename and for this one we want it to be a little more zoomed in as if we're aiming the character so i'm just going to deselect third-person cinemachine and i'm going to go to the aim one first thing we want to do is set the priority to nine or just less than the third person's in machine one because the main virtual camera that is shown depends on the priority of the camera so we don't want this one to be shown at the start and so we just want to kind of adjust this to zoom more into the player so we can adjust the camera distance so it's closer to the player and we can also adjust the screen x and the screen y depending on what you want and so just to click play we're in the aiming one and if we activate this one for example you'll see that it zooms out to that one so i'm just gonna make both of them active again and let's actually make a script so go to your scripts folder to switch between the two cameras which i've made a video on if you're interested so let's create a c-sharp script here and i'm gonna call it switch vcam and we are going to want to switch whenever we press our aiming key down so we want to be using unity engine.input system and serialize field private player input player input so we can get our actions make it lowercase here i'm just going to delete these functions for now and i'm going to be caching our aim action so private input action aim action then in the awake function let's just do aim action equals player input dot actions and type in aim and so we only really need to attach this to one camera and just change the priority of that one camera so here we can actually import using cinemachine and here we can do private cinema machine virtual camera i'm gonna call it vcam or virtual camera in the awake function let's also get a reference to that so get component virtual cameras in a machine virtual camera and then basically when we press our aim button we want to switch these two cameras so let's subscribe to our performed event for the input action so let's do on enable when the script is enabled let's do aimaction.performed so this is executed whenever our action is performed or in our case the button is pressed then let's use this syntax plus equals which is subscribing to the event however since i don't really want the parameters that come with it i'll put this underscore here and let's pipe that value to our start aim function which we have yet to make and let's do the same for cancelled aimaction.canceled so when we stop pressing the button let's pipe that to cancel aim and so here let's do an on disable function let's copy that here and here we're just going to unsubscribe from these events with the minus so plus subscribe minus is unsubscribe so let's do private void start aim and let's do a private void cancel aim so for the start aim this depends on what game object we attach the script to so let's assume that we are attaching it to the aiming camera so let's do virtual camera.priority plus equals and we can just select a number to increase it by but i'm just going to do it up here serialize field private and priority boost amount let's just do 10. let's copy that so this will basically boost the priority of this virtual camera by 10. so if you have two cameras one of them is 10 one of them is nine the one that is 10 the higher priority will be shown so if you add 10 to the one with nine then it'll be 19 and it'll be a higher priority than 10 and it'll switch over to that camera let's just copy this and instead of plus equals let's do minus equals so we want to remove that 10 that we added so then in your aims in a machine camera add your switch vcam script and make sure to drag in your player to get that player input component alright so now when we click play and we aim you'll see that the camera now zooms in and now it zooms out nice however it does so kind of slowly and we don't want that so we can change that in our main camera in the cinema machine brain as i mentioned previously in the default blend which is how it blends between the different cameras i found linear to be a pretty good one it just linearly goes from one camera to the other and i put it at point three seconds so it's a rather fast transition because this is a shooter game and we want this to be fast so now it's faster another thing is in the aims and machine camera you can actually decrease these noise values since when you're aiming ideally you'd be focused more and it'll be less noise in your aim so you can put this maybe to 0.3 on each or whatever you want so before i add the reticles for the aim i want to mention the cinemachine collider which came from the samples but you can also add it here at extension select cinemachine collider and what this does is that when you get near a wall or some sort of collider in the scene if the camera is clashing with the collider it will try to avoid clipping through that game object so for example if we don't have it on then you can see through the wall and the player is kind of obfuscated from the wall but if we enable it then it will detect the collision with the wall and try to avoid it make sure to have the follow and look at property to your player for this so you can specify what you want to collide against and what you want to ignore so if you select floor and control cube under the layer tab you can add a new layer and add in whatever you want i've already added an environment layer here you just type it environment then when you select both of them select the layer and click environment to put them under the environment layer and now we can here under collide against instead of default we can put nothing and then select environment so now it will only collide against the environment and not our player you can also specify the minimum distance from the target so if there's any object closer than point one distance away from the player it will be ignored you can also change the camera radius which i've set to point one the default is one and then the strategy is the important thing so how do you want the camera to act once it has detected a collision so do you want to preserve the distance that it has do you want to preserve the height or do you want to pull the camera towards the player whenever it's a collision and so let's just keep it to preserve camera height and then under ignore tag let's actually give our player the player tag so under the player so under the tag here i've already given it the player tag but just click it here and give it the player tag and then in your cinemachine collider just make sure to ignore the player so that it works properly right and now once i get close to the wall you'll see that it kind of glitches out and tries to maintain the height that it currently is at which it looks kind of cool actually if we change to pull camera forward you see that now it kind of zooms into the player depending on where the wall is so you can select which one you like the best i think pull camera forward is nice but preserve camera height is also nice all right so now let's add in the reticles for aiming so let's right-click and create a new folder and let's just call it sprites we're gonna put in our reticle sprites there so in google you can just search kenny reticle or it's in the description and go to cross hair pack and let's click download you can also support them if you'd like and you're free to use this in any project without permission all right so now once you've unzipped that folder you can go to png and you can select what kind of color you want there's a white retina you have a bunch of cool ones here i'm going to select this one and so you can kind of just drag and drop into your sprites folder here and that's going to be the one when i'm hip firing not zoomed in and when i'm zoomed in i want a more accurate reticle so i'll just select the 38 for the zoomed in one so let's click one control click the other one select the texture type to sprite and then click apply so now we can use it as a sprite and we can kind of just drag it onto our scene here and now let's make a canvas for our ui so right click and create ui canvas and if you're going to be using the advanced system then just click replace with the input system module but in my case i just want to add in an image so ui image and let's just drag in our sprite here reticle the hip fire reticle and you can just select the canvas and duplicate that call it third person canvas and i can actually call the first one aim canvas and this one i'm going to call it aim reticle and i'm going to replace it with the other reticle which i'm actually going to decrease the size a little bit 0.7.7 so it's not as big all right and so i'm just going to place these canvases underneath their respective cameras so the aim canvas under the aims in the machine and the third person canvas under the third person cinemachine and then if we go back to our switch vcam script here we're actually going to change the reticles as well so let's do a serialized field and let's do private canvas third person canvas and let's duplicate that control copy and i'm just going to put here aim canvas and we want the canvas so we can just enable and disable the canvas renderer directly all right and now once we have a reference to both of our canvases then in the start aim one we can do aim canvas dot enabled equals true and third person canvas dot enabled equals false and when we cancel it we want to do aim canvas dot enabled equals false and third person dot enabled equals true so we're just switching which canvas is enabled and disabled here so make sure all of your game objects are active you can set the aim canvas to off which it seems i actually switched the reticles here so i'm just going to switch their positions alright and now before we press play we want to assign the canvases that we just made so in your vcam script assign the third person canvas here and the aim canvas there respectively so when you press play now you'll see we have our reticle here and when we zoom in it will change the reticle nice also just want to mention since we added this in a machine collider for this cinemachine object let's just copy here so right click copy and then the aim one let's add in a cinemachine collider same as the other one and just right click and paste component values and make sure that your aim cinemachine has your player follow and player look at component or else the collider won't really work as well so now you see we can look around when we aim it switches the reticle awesome alright and now since we have player movement the cinema machine third person the aiming the reticle the noise the cinemachine collider now we can actually shoot the bullet which is the whole shooter part so in our player let's create a new 3d object cube to act as our gun f2 rename it gun i'm just going to move it to this side here i also just realized that i actually changed my layout because i was trying to fix a bug while i was making this video so if you're interested in this layout it's actually up here you can select whatever layout you want i usually use tall because it's just much easier to see the difference between the scene and the game and it feels less cluttered to me so sorry if that kind of tipped you off i just realized that i had it changed but yeah just put your little gun next to the player you know adjust the size as necessary i think that looks pretty good all right and now under assets materials i'm going to make a new material right click create material and i call it the gun material let's assign it to our gun and we can do it like some cool color blue that's a good color and i'm actually going to make a new material for the obstacles just so i can kind of differentiate the wall a little bit green doesn't seem like a bad color it kind of does but all right so now once you have your gun we'll also want to add under it create right click create empty and let's say barrel so this is where the tip of our gun is going to be and that's where we're going to want to shoot out our bullet from so let's move that barrel transform all the way to the tip of the gun a little bit forward so that it spawns a little bit forwards from this gun all right and then in your player controller let's add in the input action for shooting shoot action shoot action equals player input.actions and we can do shoot all right and so we want something to happen when we shoot so same as the other one on enable and on disable and start actually goes after on enable so let's change this to awake because awake happens before on enable and then after this goes start alright and so let's subscribe to our event as we did previously plus equals let's do shoot gun not shoot fun and same here instead of plus equals do minus equals all right and now we actually have to create that function so private void shoot gun so we're going to be using a raycast to do this so i don't know if you noticed but we want to shoot out our bullet from the pivot from this barrel right forwards however we want it to land where our reticle is and usually the reticle is always at the center of the screen and it never changes for most games so how do we actually get our gun to point to the middle of the reticle and have it shoot there well we can kind of cheat and instead of doing all the calculations with the gun we can actually just use the camera so we get the forward of the camera which is this blue arrow and that leads directly to the reticle because the reticle is at the center of the screen and this axis the z-axis points directly to the center of the screen so we use this to calculate where we want our bullet to hit and then we shoot our bullet from our gun and make it hit in that location and that'll make it look as if the player actually aimed and it hit the correct spot that they're aiming at so to do that we'll need to shoot a raycast out of our camera through the center of the screen until it hits something and that's basically what a raycast is basically array you shoot something from one point it goes forwards until it hits something else it's kind of a vector um but in this case we call it raycast because it's shooting array forwards it's casting the ray so to do that in unity we can do raycast hit hit and we'll be setting this variable shortly and then we can do if physics dot raycast and we have to pass in our starting position so camera transform dot position which is the center of the camera screen we want to shoot it forwards camera transform dot forward we want to do out hit so out means that this variable will be populated with whatever we hit it with inside of this function they set hit and you have to specify out here for it to work and then we can do math f dot infinity which this is the distance how far we want the ray cast to follow which i'm just going to put infinity for now and then you can also select the layer mask what you want it to hit so if you want to avoid your player you can set it to the environment tag or you can set it to the enemy tag or we can just leave it empty and see what happens so when we hit something we're gonna instantiate a bullet and we're gonna tell the bullet to go to that position and when it reaches that position it will destroy the bullet and it will spawn a d call so for my decal i'll just go to opengameart.org and you can search a bullet hole here and the first one and voila we have this nice bullet hole that we'll be using and we'll spawn that so you can just download this and drag it into your sprites folder and make sure to make the texture type to sprite so this is what we're going to be spawning when we hit the wall alright so if we hit something then let's instantiate a bullet which we actually need a reference to so serialize field private game object bullet prefab i'm gonna call it then here we can do game object bullet equals gameobject.instantiate so we're making an instance of this game object and i actually recommend making an object pool which i have a video on so you can reuse these objects instead of having to instantiate them each time so we pass in what we want to instantiate the prefab then we pass in where we want it to instantiate so for that we need a reference to the barrel so up here we can do serialize field private transform barrel transform and we have to set those later here we can do barrel transform dot position that's where we want it to instantiate position then the rotation which we can just do quaternion.identity which is just like the default rotation and then here we can specify a parent which i will serialize parent private private transform bullet parent and so this will basically place all of the bullets under this parent so bullet parent so that our hierarchy doesn't get really messy alright so now that we actually instantiate this bullet we want to add behavior to the bullet to move it forwards but instead of doing it in this player controller script which that's not its job let's actually make a new script in the assets folder and call it bullet controller and this will be attached to each bullet prefab so each bullet controller will need some things so first it'll need a reference to the decal that it's going to be spawning if it hits a collision so private game object then it needs a speed so private float speed i found that 50 works pretty well then we need a time to destroy so if this bullet is just going on forever how long do we want to wait until we destroy the bullet because we just don't want to have it go on forever and then two other things that we need are we need to know where the bullet is going so the target position and we need to set this from the player controller so let's do public vector 3 target and we can do kind of a getter and the setter which is a c sharp notation and this automatically on the back end converts it to a normal getter and setter so you don't have to write the full thing so for example if you have this getter and setter here it will convert it to a get and a set property here which is nice to have you can also have it be a private get or a private set and a public get or a public set and then we need to know if it actually hits something so public bull hit get and set and this is because we'll be programming slightly different behaviors if it's hitting something or if it's not hitting something and you'll see soon so right when this object is instantiated or enabled so on enable let's destroy it i'm just kidding uh game object destroy the game object and you can pass in time to destroy so it will destroy the game object after three seconds then in the update let's move the bullet towards the position so transform position equals vector3 dot move towards and we have to pass in our current position transform position then we have to pass in the target position and then we have to pass in the speed so speed times time dot delta time and so now here's where the hit will come into play so here we can say if vector 3 dot distance if the distance between the current position of the bullet and the target is less than some threshold let's put 0.01 and we do that because it might not ever really reach the target exactly because this might interpolate it over to the target and if we do just equals zero it might not actually reach that value so we want to have like a small threshold if it gets near enough to our target so if it gets near enough to our target let's just destroy it so now you're wondering why don't we do this on the on collision enter and we are gonna have this function on collision enter when this bullet collides with something will destroy it so then what's the point of this well let's say what if you're shooting into the air it's not going to collide with anything yet we want to destroy it after it has reached our target which will be setting a fake target so it looks as if it's going to the center of the reticle so really we're just making the player believe that the bullet is going to the center of the reticle when in reality we're doing a little bit of math trickery to shoot it out from the gun so that it looks as if it's going to the center of where you're aiming and here since we only want this to happen when there's no target so when it's being shot into the air we can do a quick not hit so if there's no target and we're getting close to our distance let's just destroy it might as well and i put this first because you always want to put in an if statement the easiest things to calculate first because if we do have a target it'll just not continue to do this calculation it'll just be like oh we hit this condition so we can just go on to the next thing but if you put this first it has to do this math and then it has to go on to the not hit when in reality we could have just checked this first and saved ourselves some calculation so on the uncollision enter here before we destroy it let's instantiate our decal so game object instantiate bullet decal and here we want to instantiate it where this collision happened so you can do other dot contacts at zero because this might have hit various things along the way and this is everything that has been hit so the contact points and look it's telling me i should use get contact instead i learned something new today so get contact at zero so get the first thing that it has contacted and let's get the point and i'm just gonna cache this here contact point equals other.getcontact at zero let's just name it contact so we don't have to keep writing this over and over again so contact that point so we're instantiating it at this point then we want to instantiate the rotation in relation to the normal of whatever it's hit so for example if it hits this wall we want the decal to spawn facing this blue arrow and in the on collision enter function it returns to us the normal which is whatever is perpendicular to our plane which in this case is the blue arrow and that's the direction where we want our decal to be facing outwards so to do that we can do quaternion dot look rotation and then we can just do contact.normal so that just means that this object will now look towards wherever this normal is facing which is exactly what we want all right and another thing i just want to add is that here if we spawn it directly where it hits unity is not going to know how to render it because now it has two objects in the same location and it doesn't really know what to render first and so you'll have kind of this glitchiness appearing if you don't actually move this point a little bit more forwards than what it hit and so i'll actually explain this a little bit more after we spawn this object so you can see what i'm talking about so back to our shoot gun script now for our bullet we can do bullet controller bullet controller equals bullet dot get component bullet controller and this is assuming that each bullet will always have a bullet controller i actually recommend maybe using an interface and doing if it has this bullet interface then do this um but for the sake of time i'm just gonna right here assume that each bullet has a bullet controller now we can do bullet controller dot target equals hit dot point so this is what we set previously and let's do bullet controller dot hit equals true so it has hit our target and vice versa if we have not hit anything then we still have to spawn this game object which if you'd like you can actually do this up here to save you some duplication some code duplication and instead of the bullet target being our hit point since we haven't hit anything we can kind of just use the camera transform forward and select a random point along that vector so in our camera the forward we just want to select a random point along this vector let's say we want it here and we're going to use this vector to determine how far it should shoot which is pretty easy to do so all you have to do is take into account the origin so camera transform.position so this is where we will be starting then we're adding in the forward direction camera transform dot forward and this is kind of like the slope formula mx plus b b is our starting position and mx is our slope and then you can just times it by some value here which we can set up here serialize field private float bullet hit miss distance not a great name i'm just going to set it to 25 and we can just times it by 25 here alright so now let's go back to our script here in the player controller in the player game object drag the barrel into the barrel transform then let's make a new empty game object call it bullet parent then under the player drag in the bullet parent into the bullet parent then we'll need a bullet prefab so let's just make a 3d object sphere call it bullet let's zoom in it's way too big 0.1.1 on the scale x and y and z so it's smaller and then we have to attach here add component bullet controller and we have to attach our bullet decal which go to assets sprites and let's just drag in our sprite here so it can spawn a decal which is huge let's rename it to bullet decal and let's very much decrease the scale to maybe 0.1 there we go let's just put the position to 0 0 zero go to your prefabs folder make it a prefab now you can delete it from the scene then in your bullet assign the bullet decal then make that bullet a prefab now delete that bullet from your scene then go back to your player and assign the bullet prefab to the player controller alright and now you'll see that when we shoot it stops there and it shoots directly into the center of the aim same when we aim it shoots into the center of the reticle and when we shoot up you see that it moves towards the center of the reticle but for some reason when we shoot in the air it kind of just chills there for a bit instead of being deleted and the decals are not spawning correctly and the reason why the decals aren't spawning is because on collision enter needs one of the colliders to be a rigid body so we can just take our cube and our floor and assign it a rigid body and we can just freeze the position and rotation for both of them since we don't want them to be moving and now if we you know shoot these decals with spawn and you'll see that they're kind of glitching out which is because unity doesn't know which one to render first so to do that we can kind of offset the decal a little bit more forward so it doesn't clash with the wall so here in contact point let's do it similarly as before with the mx plus b so this is the b we're starting here and then we're adding in a direction or a slope which is going to be dot normal times and we can do a very small number point zero zero zero one f and this is just to offset it a little bit in the normal direction so it doesn't completely clash with the wall so see now it does not clash with the wall you can also randomize these a little bit and you see that now it spawns upwards here so why is this being frozen in mid air let's take a look it's because on the player controller on the bullet controller hit i accidentally set it to true here so in the else you want to set it to false because it hasn't actually hit anything alright so now when we click play and we kind of shoot into the air you'll see that it disappears and it's actually being deleted but you wouldn't be able to really tell and one other thing i want to mention is you'll see that while you play your cursor is going all over the place and so you can actually lock the cursor to the middle of the screen by doing cursor dot lock state equals cursor lock mode dot lock so this will lock the cursor to the center of the game window so it just doesn't go everywhere so now we maximize this on play you see that now my cursor disappears and now it's at the center and you'll see that it's kind of glitching out and that's because it seems to be colliding with the gun or something on my player so i have to make sure to put the tags on as the player and so you see we shoot and then when we aim it kind of aims in and you can adjust these values as needed and let's just fix right here our gun and our barrel let's tag it as player and you see that now everything works as expected of course we can't really aim up or down but that's going to be in the next video or next videos applying animation to the character so that it looks more real and so that when you aim up the gun aims up and that's going to be with the animation rigging package you can also increase the rotation speed so it's more accurate yeah and so if your bullets do get stuck you can also add in a layer mask to the raycast if you wanted to right here in the raycast you can add in a layer mask for whatever you want if you only wanted to hit the environment or enemies so if you wanted to compare tags you can do other.gameobject.comparetag and if it's the player then just ignore the player but that's just an example if there seems to be some collision problems so yeah i hope you enjoyed this video and found it useful there's a lot of different kinds of third-person character controllers this is just one way how to make them you know some of them make the reticle move around the screen some of them have orbit cameras there's just a lot of different ways to do it but i hope you enjoyed learning about this way and in the next video i'll walk over animations and so this video actually in a way was sponsored by my patrons because we reached our goal and that goal's reward was for me to make a video on whatever the patrons voted for and they voted for a third person character controller shooter plus animations which is actually going to end up being two videos or three instead of one because there's just so much to cover and this video was already pretty long so yeah thank you so much for all of my patrons your support helps makes videos like these possible thank you so much and it also inspires me to continue making more videos and with that i'd like to thank my new patrons in the supporters here we have thank you so much for your support in the enthusiastic tier we have eric adam ben chris lome media alexander weldon trung mameli drake christian thank you so much for your support i really appreciate it and in the dedicated tier we have sophie thank you so much for your support and thank you to all of my patrons for all of your support really helps make these videos possible and if you're interested the link is in the description i offer source code early access and an exclusive discord channel and if you haven't already be sure to join our discord channel where you can ask questions chat or post memes i hope you enjoyed this video if you did please be sure to like and subscribe as it took me a while and i believe about 80 of people who watch my videos are not subscribed so if you did enjoy it please be sure to do so and i'll see you next time [Music] you
Info
Channel: samyam
Views: 28,371
Rating: undefined out of 5
Keywords: unity third person controller, unity third person shooter, third person shooter, 3rd person shooter, third person shooter tutorial, third, third person controller Unity 2021, third person controller unity, create third person controller unity, unity third person, unity3d third person shooter, unity shooter, unity3d shooter, unity 3rd person, unity 3rd person shooter, unity3d 3rd person, build a shooter, unity3d 3rd person shooter, third person camera, third person controller
Id: SeBEvM2zMpY
Channel Id: undefined
Length: 58min 44sec (3524 seconds)
Published: Sun Jun 06 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.