Making a Multiplayer FPS in Unity (E06. Shooting) - uNet Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
thanks for tuning in at brakus hello everyone and welcome to video number six on making a multiplayer FPS in unity in this video we'll finally do some shooting so we're not going to be doing the graphics for the shooting and we're not going to be doing any damaging of the players either but we are going to get the actual shooting mechanic in place so we'll create a system for you registering input find out array doing some collision checking with layer masks and finally we'll notify the player the server that a player has been hit so that the server can send out a debug log statement saying that this player has been hit to all clients that's kind of how far I hope to get today and before we get started I of course want to mention that you can get the full project folder with all of the previous versions on github links in the description and also if you have any questions and can't get that to work within i suggest you visit the practice forum so let's get started so let's start by making a player shoot script so let's select our player hit add component and type in player shoot and simply create that we can then double click it to open it up in Visual Studio and also I want to go into the project panel here and create another script which is going to be the player weapon script and this is simply going to be a fairly empty class that's just going to store a couple of members that will host information about our weapon at least for now so let's double click that - and now we should have these two so in the player shoot script here instead of using system dark elections we want to be using unity engine dot networking and of course want to derive from network behavior as we've done with any network networked object and I simply want to delete all of this and the first thing we want is is basically a reference to our player camera because when we are shooting array we wanted to shoot from the exact center of the camera and therefore we need a reference to it so let's make this a serialized field so we can make it private but still drag something into it in the inspector and it's going to be a pirate private camera and we'll just call this cam and just to make sure that we've actually inserted a cam into this slot we'll just check in the start function if cam is equal to null and if it is well then we want to throw an error so debug that lock error and we want to just say no camera referenced and we can maybe just tell ourselves that it's the player shoot component saying this and then we can simply disable the component there we go then of course we want our current weapon and at some point we want to do some our weapon swapping and also a way to swap the graphics of the weapon but for now our player weapon class will simply store stuff like damage so we need a public and we will just make this public for now so that we can access it in other scripts and this is going to be applic player weapon and we'll just call this weapon and simply close that off we'll fill in the values in the inspector then we can hop into our player weapon component here and remove the system to our collections namespace and make sure it doesn't derive from anything this way we have a standard public class inside of this public class we want to create a pub a few members so the first one is going to be a public string and this will store the name of our our weapon and we could make this a charged laser or a more modern name we'll just call this a Glock and I'm sorry but I don't know any model names for Glocks I'm sure that there are so many different ones but this will do for now the weapon fanatics are probably going to call me out on that so then we're going to have a public float storing the damage you can make that an integer if you want but I like to have the have full control over that and a public float storing the rain Jen will just default that to 200 so that's quite a long range here change my mind good and of course we can do stuff like fire rate whether it's single fire burst and we can do shotgun stuff and all of that and we'll definitely have a look at some of that stuff at least later but for now this is all we're going to need so let's say that head into the player oh I forgot one important detail and this is very important we need to tag this class as a system dot serializable class so this class needs to be serializable because what that means is unity will know how to save and load this class and that way we can change these values in the inspector if it doesn't if we don't tag this as a serializable class we won't be able it won't even show up as a variable in the inspector so that's very important when dealing with classes in unity so next up let's let's create the update method here so void update and in here we simply want to check if we've gotten some input so if input that getbutton and for now would you do a get button down so this is a single fire weapon and the button that we want to check for is the fire one and this is again one of those default inputs as defined in unity and actually I want to change this a bit so if we go under edit project settings and then input you can see the fire 1 input here and you can see that it has this positive button left control and I think that's super annoying so let's remove that so we don't shoot whenever we press control we simply want to be able to shoot using the mouse key and we of course want this to be key or mouse button cool then we can head back into visual studio and if we get this button down well then we want to call some kind of shoot oops not player shoot some kind of shoot method going here and I think it's time to go ahead and make that now and this is just going to be a private method of course cold shoot and it's not going to take in the arguments and this is where we do our actual ray cast so let's start by making a private ray cast hit I will just call this hit and we want to make this variable because the way unity ray casting works is that we send out a ray by calling a method and we have this out variable and what this means is that we define this ray cast hit we declare this here and then we put it in as an argument to the function and the function will then fill out information into this variable so basically the hit variable here will store information about what we've hit and a lot of other stuff where we hit it then and all that so now we can simply say that if physics dot ray cast so if we hit something with the rate that we are going to be shooting here then the then this logic here will be called so we hit something so shooting in Ray Ray's in unity is quite a bit of syntax actually so if physics that Ray cast and then we want to define the start of our ray and that is going to be our can dot transform dot position that's a vector three of the position of the camera then we want to have the direction you can see just how many overloads this has so we want the direction that we want to shoot in and that is going to be can don't transform dot forward and then we want to input I think it's time to input either the max distance or out the hit I think it's out hit then the distance and the distance here is going to be weapon dot range and finally we want some kind of layer mask so we'll define that up here so basically when we're shooting out array we want to be able to control what the array will hit so we won't only want this to be able to hit objects that we can actually see not visible collide invisible colliders or anything like that and we want it to be able to hit other players we don't want it to hit triggers and things that we only use for controlling gameplay State and we don't want it to hit ourselves so in order to make sure that this won't happen we create another serialize field and this is going to be a private layer mask I will just call this mask and this will allow us in unity to control what we hit and we simply put that in here so I think this is the correct order if not we'll get an error so we've simply hit something and we know everything about what we hit we've hit by using the hit variable here so you can see if I if I do a dot there we have the point we've hit the normal that we've hit of the surface the collider that we hit the distance to the point we hit and and all that stuff that's a lot of useful information and we can do a lot of stuff based on that information okay so for now we can simply do a debug log statement here saying that we hit and then plus hit dot Collider dot name cool so now I've saved that and everything here should be working and now when we hit back into unity we want to select our player and make sure that we fill in some of these settings so we can expand our player here and drag in the camera we can see that we now have the weapon here and that's a glog with the damage of ten and a range of 100 and we have this mask and for now we want to set that equal to everything and if we go in and test this now there's a great chance that this will just hit our own player but that's fine but we just want to make sure that this is working so if we hit play and select land host and look down at the console here and then click you can see we actually hit the floor prototype that's great so we didn't hit our player there and you can see if I just shoot into the air we don't hit a thing and it's the same when we shoot at these cubes because they don't actually have any colliders so maybe we should actually just go ahead and quickly create some colliders for them so simply select all three and we can actually just add a box Collider for all three simultaneously so now that we have that in place we can go in and hit play and maybe shoot some of those so shoot one there and you can see that it says down here what we've hit so that's perfect don't worry we'll do a mouse lock at some point it's really annoying right now it doesn't lock to the center of the screen I know great so now that we have that in place we want to make we want to assign our player to a certain layer once we set him up and all other players to another layer this way every local client with hat will have a setup where their own local player is on one layer and all other remote clients or remote players on another layer and this way we can simply set the mask here to only hit remote players and not local player so if that sounds weird fine but I'll just show you actually how easy this is one thing I will go ahead and do is simply tag our player as player because we're probably going to be needing that at some point and it also just looks really clean so under the layer here we don't have enough layers to work with already so let's go ahead and add a new one we want to have a local player layer and a remote player layer and of course we could just go ahead and assign that in here and we are going to do that for the local player yes change children but we want to assign it the or change this to remote player through the player setup script so if we double click this we can see that we have this code that in the start method will check if we are not the local player and then it wants to disable a bunch of components and if we are well then we want to disable the scene camera well we can simply use this to change the layer also so first off let's just organize this into a separate function I mean the component disabling here so we'll just make a void disable components just so our start function won't get too crazy here so just put that in there that looks cleaner and then here we'll simply call disable components and then we'll make a another method here and we'll call that assign remote layer and we'll call that in here so if it's not a local player when then we want to assign it to a route to the remote later on this client so and in order to do this all we have to do is specify the name of the remote layer so we'll just make that a serialized field up here so string remote layer name I will default that to remote player and then down here we are calling that here we can simply say that I believe layers are stored on the game object so game object layer yep equals layer mask dot layer to name or name to layer and in here we'll simply put the layer the remote layer name there we go so basically we have to write it we can't just set it directly because a game object that layer once an index or an integer value because all layers are assigned numbers and they're just represented in the unity editor by strings but they are in fact numbers and therefore we need to call this utility function that will take the string and convert it to the index that we want and then put that back into the game object dot layer so now that we have this in place we should be able to see if we are connect multiple clients that we are able to hit each other and that they're the layers assigned are correct so let's try and build this by hitting control B or command B if you're on the Mac and this should hopefully be working so it's opening up there and we can start the game in unity hit land host start the game here hit land client and if I just hit into unity here and have a look in the scene view we have this one player this is our local player that's the one that's spawned first on this client and then we have the other remotely connected player and you can see that's on the remote player layer and of course if we were able to inspect the properties fry this player we would see that this situation was reversed good so if we now hit into unity here we should be able to hit each other here so if I shoot him that is not working oh yeah it is it worked but for some reason I also hit the floor there I don't know but it when it went through for some reason let's just have a look at that that's kind of weird behavior such registering twice here oh that's because we are shooting for both players of course I don't know what I was thinking there so that's because we have to go in and disable the component we'll look at that in a sec but you can see that it says we hit the player there and that's all that we need so now that we know that this is working what isn't working is that we don't have any checks inside of our players chute to see to make sure that we only do this for the local client because when I when we get the input down we don't want to fire on other players behalf which was what we just did so we could do a check in here saying that if we are not local player and all that but instead what I want to do is use the same method that we've done for other components which is simply adding them to the components to disable array so let's just expand that to one more and drag in the player chute and that should be on so now when we save this and build this and put that there and run this here land host and here client I'm just going to go into unity here and shoot the player will see that there's only a debug deadlock statement being called here what you will also notice if we go in here and shoot around shoot the player then shoot here and shoot over there we've hit a bunch of things this console dot log or this console doesn't update so currently we are only written registering this shooting and the fact that we've hit something locally on the client we need a way to send this information out to the server and that's what we'll do next so when we want to send this information about what we've hit and the fact that we've hit a player out to the server so that the server can distribute it among the clients we need some kind of way of recognizing different players and therefore I want to introduce the concept of a unique identifier some kind of ID that will allow us to know what player belongs to where and it's actually very simple because right now when we spawn a player in here you can see that they are all called player clone well when we attach a network identity object a component to an object that's going to have a unique identifier already this has an ID it's just not showing anywhere so for the sake of convenience let's take this ID and let's add it to the player name that way we can simply check for objects with a certain player name in order to tell them that where they were here they should apply damage or whatever we want to do so in order to do this let's again go into our player setup script and this is starting slowly to become a longer script and in here depend no matter if we were registered as a local player or not we want to set the name of the player so in order to do this let's simply get a reference to the network identity component and we want to simply do this without checking if it's there or anything because whenever we have a network behavior well that requires that component so we don't even need to type require component up here that's kind of done already so let's get a string ID and set that equal to get component of type network identity and then we simply want to say dot net ID and close that off and I think we should go ahead and combine this with the fact that it's a player so let's simply type player plus and then get the net ID and I want to have a space in here also you could also create a variable up here for the name of the player sort of say other than the ID but I think this is fine hook hard-coding it here for now in a future video I want to keep track of what players are currently in the game and all that now that we have this string we simply want to assign it to the object so we can simply going in here and say transform dot name equals underscore ID and that's basically all we have to do I mean it's that easy so let's create a void here and we'll simply call this the register player because that's basically what we're doing we assigning him an ID to make him unique and therefore registering him on in the scene so register player and later we'll register him to some kind of dictionary and then we want to assume you can paste those in there so now when we apply and so the gland host you can see that he's registered as player one and the next one is going to be player two you get the system cool so now inside of our player shoot script we can go ahead and call a method on the server and simply give it the ID so this here is a local method and therefore I want to mark it as client so this is only called on the client and never on the server but the next thing here is going to be what is called a command so therefore we want to mag it as a command and it's a good idea when having command functions when naming command functions to start them with the CMD just to know that it's a command that we're working with and commands are basically methods that are called only on the server so this here is going to be player shot or player has been shot or till server player is shot you can call it whatever you want I'm simply going to say player shot and then we want to insert some kind of ID and inside of this command all we do is we say debug deadlock and then we will say ID plus has been shot that's all we need to do here for now later we'll do damaging so in here if we actually hit something and we want to check if it's a player that we've hit so if hit done tagged hit Collider tag is equal to player we could do something like that we could also check if on the layer then the object resides on is equal to remote player we can do a bunch of stuff here but I think we'll just check if it's if it has a tag of player and we could of course not hardcore code this I don't want this to show up in the inspector but I think I will declare that up here so let's just make this a private and it's going to be a constant and it's going to be a string and we'll simply call this the player tag and set it equal to player like this and then we can simply take that player tag and input it there and then we want to call our command player shot and we wanted to give hit dot Collider dot there we go finally so let me just want run through this so if we register some input we shoot and this is called on all local clients but because we've made sure that the components is disabled for all other than the local client it's only cold on the client that is actually doing the shooting and then we shoot out array and if it hits we check if it hit a player and if it did we call a method on the server called player shot where we give it the ID which is also the name in the hierarchy as an argument and then here on this server will print out that this certain player with this ID has been shot so what you could also do here if you wanted to then let's say remove that object or damage it in some way this we could use came out find and then insert the ID here and that would give us the object so that we can then destroy it so we could go in here and say we want to destroy this game object dot fine and that would kill off the player but we're not going to do that because of two things first off we have been talking about what happens when players die and all that so simply holding this the D straw method wouldn't be a good idea and also game object that find is really slow and therefore we are going to add this player dictionary later that will pair players with IDs and remove them when they disconnect and all that so now that we've saved that we have the player setup working we have the player weapon everything should be working and if we just go ahead and hit play here you can see that nothing is happening when we just shoot around so let's go ahead and build this so that we can test it up with another client and the cool thing that we should be seeing now is that when we hit a player here it should throw a console log here also so we have that like working we want to slick host here and client here and let's go ahead and shoot our player shall we and it's not updating for some reason it's not updating in here either so something is going on I'm just going to check what is wrong here and then I'll get back to you in a second okay so I found this really dumb mistake that I made and you've probably known all that all along but this of course doesn't want to be in quotation marks this is just a variable so let's make that player tag so that we don't search for a tag of player tag that would just be stupid so let's try this again remove that Bildad and finally it should be working hopefully it's in some way so let's set like land host let's select client let's go over here and the shooter player there we go so it says player 1 has been shot and player 1 is the editor client and again if I shift over here and shoot the other guy it says player 2 has been shot and you can see just how clean that is now the client knows now the server knows and therefore all clients have the ability to update their game state based on the fact that someone has been shot so that's the end of this video I hope you liked it and I'll see you in the next one
Info
Channel: Brackeys
Views: 205,809
Rating: undefined out of 5
Keywords: unity, unity3d, tutorial, asset, material, materials, how, to, howto, learn, learning, course, series, tutorials, workflow, game, development, develop, games, programming, coding, basic, basics, C#, shoot, shooting, weapon, First-person Shooter (Media Genre), Unity (Software), Multiplayer Video Game (Website Category), raycast, 3d, raycasthit, bullet, damage, network, server, command, client, attribute, ID, player, unique, identification, intermediate
Id: QB2dt7kGlV8
Channel Id: undefined
Length: 29min 12sec (1752 seconds)
Published: Sat Oct 31 2015
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.