Finishing the archer! - Complex Enemy Behavior - 2D Platformer - Part 19 [unity]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is up guys welcome to Barden my name is Heinrich and today we're finally finishing off or arch her enemy so last time we just went about implementing all the states that we had already created for the other enemy and so today we're gonna create two new states specific for this enemy so that would be our range attack state and our dodge state let's start off with our dodge state so let's head back to unity and then we can go to our scripts folder enemies folder and then into our state's folder we can then go ahead and create a new C sharp script that we're going to call Dodge State we can then go into our data folder and create a D underscore Dodge State c-sharp script Sophy underscore Dodge State and then finally we can head to our enemy to specific folder and create an e to underscore Dodge state script we can then just go ahead and open all three of these up so there's our e to dodge state then we need our Dodge state itself and finally our data script now let's start off of getting our data script ready so we can just go ahead and delete this code make it inherit from scriptable object and then let's go and open up a different data script just so that we can get our create asset menu line paste that up there and we'll change the file name to new dodge state same over here cool so our data script is ready let's take a look at the Dodge State itself we can do the same thing and just get rid of this code and this time we'll make it inherit from State and then we can just go ahead and generate the constructor like that and next we need to get a reference to our state data so we have a protected D underscore dodge state called state data we can just go ahead and add that to our constructor so d underscore dodge state cold state data and then in the constructor we say this dot state data equals state data and then next we can generate our function overrides and we don't want the first three like usual click OK and there we go so our dodge state is ready so before we start adding anything to our dodge state let's first think about what we want the Dodge state to do so let's go ahead and take a look at our state machine diagram so you can see what our conditions are so as you can see from our player detected state if our player is in close range so our close action range then we want to Dodge and so on our transition to our melee attack state we have the condition that the player is in the close action range and we have already dodged so the archers first instinct when we get close is going to be to dodge and then we'll have some sort of dodge cooldown timer and if the player gets close enough again the enemy will hit the player now once we have dodged if the player is in the close action range then we're immediately going to punch the player otherwise if the player is not in the class action range but the enemy is still detecting the player we're going to go into the range attack state and then finally if we dodge and we no longer detect the player then we're gonna go to the look for player state so that should be simple enough so let's go ahead and go back to our script and we'll start off by declaring two boolean's these two boolean's are going to keep track of whether the player is in the close action range or if they're in the max aggro range so we'll start off with a protected pool called perform close range action and then next we have a protected pool is player in max aggro range like that now we can just come to our ducek's function and add those two so perform close range action is equal to entity dot check player in close range action like that and then is player in max aggro range is equal to entity Koscheck player in max aggro range now for the dodge itself we're going to use the same function we use for the knock back when the enemies get stunned so that means we need to know when our enemy is grounded and we know when our dodge is over so let's declare two more bowls the first one is going to be our is grounded so we have protected pool is grounded and then next we have a protected pool cold is dodged over like that now we can come to our ducek's function again and add our is grounded so is grounded equals entity dot check round just like that then we need to come to our enter function and make sure we remember to set is dodge over to false so is dodge over equals false next in our enter function we want to set the Dodge velocity so before we can do that we need to come to our D underscore dodge state class and declare the variables that we need so we'll start off by declaring a public float that is going to be our dodge speed and then next we have a public vector to that is our dodge angle we also need two more floats that is going to be our dodge time which is the same as our knock-back time just a little timer that makes it so that our is ground does not detect ground and stop our movement so we have a public float called dodge time and next we have our dodge cooldown so we have a public float called dodge cooldown and let's just set some default values so for our dodge speed that's set that equal to 10 and our dodge time is going to be 0.2 dodge cooldown by default we're going to set it to two perfect now we can come back to our dodge state and then in our enter function we can say entity dot set velocity and remember we have to set velocity functions one that just takes in a single velocity value and then one that takes in a velocity angle and direction and so we're going to be using the second one and we'll pass state data dot dodge speed as our velocity state data dot dodge angle as our angle and then finally our direction is going to be negative entity dot facing direction now in our logic update function we're going to determine whether our enemy has dodged and is again touching the ground so the Dodge is over so in our logic update function we can say if time dot time is greater than or equal to start time plus state data dot dodge time and is grounded is true if this is the case then we can say is dodge over equals true and that's basically it for the dodge state simple as that so now before we take care of transitioning to our dodge state let's go ahead and set up our enemy to specific dodge state so you can come to our e to dodge state class and then we can get rid of this code and make it inherit from Dodge State next we can generate the constructor and then set up our reference to our enemy to so private enemy two called enemy and then in our constructor we can just add that so enemy to enemy and this dot enemy equals enemy then we can generate our function overrides so quick actions generate overrides we don't want the first three check okay and now we can set up our transitions so in our logic update function we'll start off by saying if is dodged over because any of the transitions are only going to have and once the dodge is over then let's take a look at our finite state machine diagram so we either want to transition to our melee attack state or our look for players state because we don't have our range attack state yet so just put these two in for now so when we go to our melee attack state that means he's in the max range and he's in the perform close action range so we'll say if is player in max our range and perform close range action then state machine topped change state to enemy dot melee attack state else if so in this case our player is not in our max aggro range so else if not is player in max aggro range then we want to say state machine dot change state to enemy look for player state and if you want to you can also make it so the enemy turns immediately when going into the liquid player state so maybe in the case where we dodged past him he will turn immediately and look at us but I'm just gonna leave it as is and that's basically all we need in here now we just don't need to add the transition to our range attack state so let's leave ourselves a little to do so to say ranged attack state like that okay now let's take care of the transitions into the dodge state so if we look at the diagram again we can see we only have one transition and that is from our player detected state so let's go ahead and go to our eetu player detected state so in here we're gonna add some other if statements in our perform close range action if statement so we want to set up the transition to our dodge state now this is supposed to happen if performed close range action is set to true but we also want to transition to the melee state if our dodge cooldown has not yet reached 0 so in order to determine this we need to get access to the start time of our state's from different states so let's actually go ahead and open up our state script which is in our state machine folder state and as you can see we have our protected float start time so let's just set up a public getter and a private setter for this so now this means that we can find out what a certain states start time was from other states which is gonna come in really handy so let's go back to our e to player detected state and then in our if perform close range action if statement will say if time time is greater than or equal to our enemy dot dodge state which we still haven't set up dot start time like that not just to make sure this is correct let's really go to enemy two and let's go ahead and set up our dodge state so first we need our public key to underscore dodge state cold dodge state and this has a public getter and a private setter and then we need the data so serialize field privates D underscore dodge state call it Dodge state data and then we can call the constructor so dodge state equals a new e to underscore Dodge state will pass this as our entities state machine as our state machine dodge as our animation name and then we have Dodge state data as our data and through this as our enemy to so back Annie to player detected state this should work we still have an error on start time right so we actually want to set it to public and instead of private set it is protected set like that perfect so back in our player detected state yep that works so we can now access the start time of our dodge state from our player detected state so we're going to use this as a reference to see when did we last start so if our current time is greater than or equal - our last dodge time plus or cooldown so we also need access to our Dodge cooldown time so let's go to our enemy - class and that is this Dodge state data so instead of private let's just make that public and then give it a getter and a setter so public get private set and then back in our protected state we should be able to say plus enemy dot dodge state data dot cooldown time so if this is the case then we want to dodge so state machine dot change state to enemy dot dodge state else so if our current time is not greater than that we want to melee attack so we can just put this in here okay so now he turns out that we can't use serialized field with our dog state data like this it won't show up in the inspector so I'm not quite sure what to do to fix that yet but for now we can just leave it as public and then just get rid of this this way we'll be able to access it from our state but we can also set it in the inspector I'll find out how to fix this and then update it in a future video if you know how to fix this please share in the comments okay so let's head to unity and then we just need to create our dodge state data so let's head to our enemy two data folder then let's create a new data state data and we're creating the dodge state data we'll just call it e to underscore dodge state data and as you can see everything is set up for us except for our dodge angle which we'll just leave as 1 on the X and 2 on the Y actually no I'm wrong we'll leave it as 2 on the X and 1 on the Y to give our enemies some more distance then let's come to our enemy to game object and drag that in loop just like that and then we just need to set up the animations so let's open up our animator and see what we have going on make sure we click on our alive game object so let's start off by creating our boolean parameter which is just Dodge drag that up and if you remember correctly we made these three animations for our Dodge so our Dodge start Dodge up and Dodge down so let's drag up our Dodge start animation just put it around here and let's make a transition from empty to that animation we can click on it make sure has exit time is not ticked and then set the transition duration to zero our condition is Dodge is true so when we dodge we're gonna come into this animation and we're gonna let it play completely before going into a blender II with these two animations so we can actually delete these two and then you come and create a new state that's gonna be a new poll entry and we can just call this our Dodge blend tree from our Dodge start animation let's make a transition down to our blend tree and in this case has X the time should be ticked and we should set the exit time to 1 this means our Dodge start animation is going to play all the way before we transition to our blend tree we can also just set the transition duration to zero seeing as we have an exit time we don't require a condition for this now go ahead and double-click on the blend tree click on the blend tree in the middle and here we have our list of motions let's just the different animations we want to play so let's hit the plus icon and create a new motion field and we can do that twice because we have two animations and then let's just navigate to our animations folder then into our enemies folder and I see here I still have my enemy 1 animations just drag those into the enemy 1 folder and then in our enemy 2 folder here we have our Dodge down and our Dodge up animations so in our blend tree let's drag those two in so Dodge down Dodge up you might just have to move them around so as you can see we have a blend type that is 1 D so we have one variable that's going to control these animations now order to determine which of these animations need to play we need to know the Y velocity of our enemy so as you can see under our parameters it added a blend float parameter for us so we can just go ahead and click on that and rename it to Y velocity like that and now we can use our Y velocity to control which animation plays we just need to go to our entity script and pass in our Y velocity first but for now let's finish setting this up so as you can see if our Y velocity is zero we're playing enemy to dodge down this is not quite right when it come to the inspector and untick automate threshold and then we gonna set the threshold for Dodge down to negative one so now if our velocity is negative one then the dogs down animation is gonna play so any Y velocity less than or equal to negative one will result in Dodge down then as we go up as you can see once we get to zero so actually anything lower than zero is going to play dodge down anything greater than zero is gonna play Dodge up perfect we can then come out of our blend tree by clicking on base layer up here and now we can set the transition back to empty this transition is going to come from our blend tree so make a transition from there to empty click on it has exit time is not ticked transition duration is zero and the condition is that Dodge is false now we just need to go to our entity script and pass our Y velocity to the parameter so let's go to our scripts and then go to the entity dot CS script then in our update function over here we can just say annum dot set float and the float name that we want to set is going to be Y velocity and we'll just have to go back to our enemy one and also add this parameter to the animator if we don't want to get any errors and the value we want to set it to is our rigidbody velocity dot Y so let's go back to unity and let's go to enemy one alive let's add a float parameter we'll just call it Y velocity oh it's going to be very important that we always split the same way in all of our enemies but that should be good let's test it out so on our enemy too if we get closer than this circle over here our enemy should dodge let's see what happens see if it works what we tried to punch me looks like he did dodge yeah he does dodge but it's not quite right yet I think we have to increase our dodge speed so it looks like he's not going up high enough and then the dodge time is still affecting whether or not he stops so let's click on enemy to go to our dodge state data and let's change the dodge speed to 30 let's try that one out that might be a little bit too much what it works let's try 15 maybe it's a little bit better more like that he's bouncing like that though okay so he's currently detecting us as you can see if we get close after he dodges he tries to punch us instead but why is he bouncing like that maybe let's just keep his dodge angle at 1 1 I also think his dodge distance or his close-range action distance is a little bit too close so let's go ahead and go to our base data and this is our close-range action distance let's just increase that slightly put it around there so where he also get damaged when we punch I like it perfect Sauer Dodge is working now if we don't want him to dodge off of ledges it's as simple and as complicated as just checking behind the enemy to see if there is a Ledge it's easy enough if he's right on the edge to see okay there's no ledge there so don't dodge but we might want to set up something where we can determine how far back the enemy is going to dodge and then at that point check and see if there is ground and then only if there is ground then dodge back but I haven't quite figured this out yet but it is something I'm going to add to this enemy but we're in good shape so I think now we can head on to our ranged attack so once our enemy detects our player if we don't get within our close action range and our action time is over we're going to shoot an arrow at the player then once we've shot the arrow if the player is still within the max aggro range we're gonna go back to play detected else if we don't see the player we're gonna go to look for player so let's go ahead and go back to unity and then let's head to our enemies folder States folder and let's create a new C sharp script that we're gonna call range attack state like that we can also go to the data folder and create a D underscore ranged attack state and then we can go to our enemy to specific folder and create our range attack state there so e to underscore ranged attack state we can go ahead and open all of those up so we have Val one this one and this one perfect again let's just start with our data script and go ahead and delete all of this code make it inherit from scriptable object and then we can just come and copy this again throw it on there and now instead of new dodge state data it's going to be new ranged attack state data like that and that's good next we can come to our ranged attack state get rid of this code and then make it inherit from attack State now remember with our melee attack instead of having a melee attack that inherits from state we created another state called attack state that is a just a general combat state and then are different types of attack inherit from that instead so a melee attack and ranged attack both inherit from attack state the attack state then takes care of all the general things so we're really not going to do a lot in this state the first thing we to add is our constructor so let's go ahead and generate that and then we need to get a reference to our state data so we have a protected D underscore range attack state and we're just calling it state data then in the constructor we say D underscore range attack state called state data and then in the constructor this dot state data equals state data like that then we can go ahead and generate the function overrides we don't want the first three click OK and perfect now let's just go ahead and bring up our attack state so as you can see our attack state takes care of keeping track of our players so we don't have to do that it sets up all of our interactions with the other script which sets the velocity to zero and sets our is animation finished equal to true so all we need to do in our range attack state is spawn the projectile on the attack transform or the attack position so let's go ahead and go to our D underscore ranged attack the first thing we're going to need is our projectile so we'll have a public game object that's going to store with the projectile prefab then next we need to know how much damage our projectile is going to do so we have a public float called projectile damage then next we need to have this speed that I projectile moves at so public float projectile speed and then finally we need to have our projectile travel distance the reason we need this is because it's a platformer I want the arrow to move in a straight line for a certain distance and then start getting affected by gravity and falling down so this projectile travel distance is going to be how far does the projectile travel before it starts getting affected by gravity so we have a public float projectile travel distance now you could also set up all these variables on the projectile itself but I'm going to keep these things like attack specific and I'm going to have a different state for all the different attacks so if my enemy ends up having multiple ranged attacks it's going to have a different range attack state for each one so by default let's just set our projectile damage to 10 and our projectile speed to 12 like that now I said in our range attack state the only thing we need to do is instantiate our projectile now when we instantiate our projectile we need to take all of these variables and pass it to our projectile but before we can do that we need to set up our projectile so let's go back to unity and then let's go to our scripts folder and let's just create a new folder called projectiles in this folder let's create a new seater script and this script we're just going to call projectile as well now I'm considering maybe in the future adding magic and different types of projectiles to the games so we're probably going to end up using some sort of inheritance system for that as well but for now we'll just leave this projectile script super basic it's just a once-off script and we can build on it in the future now let's create an empty game object that is going to be our arrow we'll just call it arrow and don't forget to reset the transform and now before we can add a sprite to it we actually need to import that so let's go to our sprites folder and I've included their projectile sprites in the description so we'll just create a new folder called projectiles again go ahead and open that up and then just import your arrows go ahead and click on that and set the pixels per unit to 16 the sprite mode is multiple filter mode is point no filter and compression is none hit apply and then let's open up the sprite editor now I've included two arrow sprites that I drew you can use whichever one you like I'm gonna use the one on the right so we'll say slice grid by cell size and the pixel size is 32 by 32 go ahead and hit slice and now we have our two arrows then hit apply and we're good now let's click on our error game object and let's go ahead and add our sprite renderer you can open that up and then let's just drag in the sprite that we want to use if you don't see it don't forget to come to the sorting layer and change that to enemy also make sure you're actually looking at it we might end up making a projectile layer later but for now we'll just keep it on the enemy layer perfect next we need to add a rigidbody 2d component to our arrow and let's just open that up and set the collision detection to continuous we can set the gravity scale to 8 but we might mess around with this later depending on how fast we want the arrow to drop down to the ground and I think that's everything we need for now so let's go ahead and go back to our code now our projectile is going to interact with our player the same way any attack does by using our attack details and sending a message to whatever it hits so let's go ahead and get rid of this code and start off by declaring a attack details variable so we have a private attack details cold attack details and this is going to store everything we need next we need to have the speed of our projectiles so we have private float speed and then we also need to have a reference to our rigidbody so that we can apply that speed so we have a private rigidbody 2d called our B so now we can go ahead and call our start function and in the start function let's start off by saying rigid body equals get component of type rigidbody 2d and then let's immediately set our gravity scale to zero so our B dot gravity scale equals zero point zero f then we can move our projectile by saying rigid body dot velocity equals transform dot right multiplied with our speed now as I mentioned earlier we want the projectile to travel a certain amount of distance before falling down to the ground so we need to come up and declare our private float travel distance and then we also have to declare a private float X start position so once we instantiate the projectile it's going to say ok this is my X position and then it's going to use this position with our travel distance to determine when to turn on gravity so let's come to start and say X start position equals transform dot position dot X now let's go ahead and create our fixed update function and in our fix update function we can say if math F dot ABS so the absolute value of our X start position - transform position dot X is greater than or equal to our travel distance so the math f of abs accounts for traveling left or right so if this is greater than our travel distance then we want to turn or gravity so let's actually go up and declare a boolean that's gonna keep track of if our gravity is currently on or not so we'll have a private pool called is gravity on and then in our start function we'll just make sure that is false so is gravity on equals false then in this function we can say is gravity on equals true now we also wanna make sure this only gets called once so let's add that as a condition to our if statement and say and is gravity on does not equal true so not is a gravity on so now we're turning on gravity meaning we have to set our gravity scale to something so let's come back up to our variables and let's declare another private float but this time it's going to be a sterilised field private float gravity then back in our if statement will just say rigidbody gravity scale equals gravity now once we've fired the arrow we have two options the error can either hit the player or it can hit the ground so we need to be detecting both of these so let's come up to our variables and let's create two layer masks so I'll have a sterilised field private layer mask called what is ground and then we have another serialize field private layer mask what is player so this means on our projectile we need to be detecting this using some sort of physics thing so we're going to set up a damaged position on our Arrowhead so we'll have another serialize field this time it's a private transform that we'll just call damage position and while we're at it let's also create another private boolean that's going to be cold has hit ground and we're gonna use this has hit ground to basically turn off the projectile once we hit ground so it can no longer damage the player if we walk over it so let's come back down to our fixed update function let's just create another if statement and inside the if statement will say not has hit ground and then let's just move this if statement into here like that and now before this happens so in our if not has hit ground let's do the collider checks so I'll declare a Collider 2d that will call damage hit and we'll just set it equal to physics 2d dot overlap circle and our for our overlap circle we need a position and a radius so we actually need to come up and declare a damage radius so we have another serialize field private float that we call damage radius and then back in the function we can say damage position tough position damage radius as our radius and then finally we pass it what is player as our layer mask now we'll create another Collider 2d that we'll call ground hit and we'll set this equal to physics 2d dot overlap circle and again we'll use damage position as our position damage radius as our radius and then for our layer mask we use what is ground now after this we can say if damage hit so we have detected something in this case our player then we want to say damage hit dot transform dot send message so it says take the object that we hit and send it message and the message we want to send is damage and the parameters we want to pass is our attack details like that then after we hit the enemy we want to destroy the arrow so we'll say destroy game object now in the case where we hit the ground so if ground hit then we want to say has hit ground equals true then we're going to set the gravity scale of the arrow back to zero so it doesn't keep falling so rigid body dot gravity scale equals zero and then finally we want to set the velocity to zero so rigidbody dot velocity equals vector 2.0 and that's perfect now let's just go ahead and call our on draw gizmos function so that we can draw our damage position just so we can see where it is so let's come down to the bottom and say on draw gizmos and then in this we just want to say gizmos dot draw wire sphere and the parameters for this is going to be our damage position doc position and our damage radius now the last thing we want to do is make sure when gravity is enabled that our arrow is going to rotate in the direction that it's falling this we're going to do in our update function such as go ahead and call update and then in the function all we have to say is if not has hit ground then if is gravity on so we only want to rotate it once gravity is on we're gonna say float angle equals math F dot a 10-2 and so what a 10-2 does is it just returns an angle between two lines so if we have a triangle and one side is going to be our X velocity and the other side is our Y velocity then it's going to return this angle so for our float why we pass rigidbody dot velocity double Y and for our X we passed rigidbody dot velocity dot X now atan2 does return this in radians so we have to convert it back to degrees and that's as simple as multiplying it with math F dot radians to degrees now that we know the angle that we want to rotate the arrow we just have to rotate it with transform dot rotation equals quaternion dot angle axis and what dot angle axis does is it creates a rotation which rotates our angle degrees which we pass to it around a certain axis so to this we're going to pass our angle and as our access it's going to be vector three dot forward so vector three that forward is basically pointing into the screen and that's the access we want to rotate around just like that now the reason we have this in two separate if statements is because before we do this we need to update our attack details exposition so before this if statement let's come and say attack details dot position equals transform dot position like that and now we're basically done with our projectile script the last thing we need to do is just create a function in this script that sets up everything once we spawn their projectile so let's come down to the bottom and let's create a new public void function this time public because we want to call it from different scripts and we'll just call it fire projectile and as parameters to this function we're going to take in the speed of the projectile oops so we have a float speed then we have a float travel distance and then finally we want to pass in the amount of damage the projectile does so float damage like that now in this function we just say this dot speed equals speed and this dot travel distance equals travel distance and finally attack details dot damage amount equals damage just like that and we're basically done with the projectile script so let's go back to unity and let's throw that script on here so we can go back to our scripts folder projectiles and then click on our arrow game object and just drag this on simple as that now for the gravity let's just set that to three start off with cancer the damage radius yet what is ground is ground what is player is player and then let's create a child game object that is going to be our damage transform or damage position let's go ahead and drag that in and now if we set a damage radius we should be able to start seeing it so let's just make it 0.15 and then position it at the tip of the arrow like that perfect now let's go to our prefabs folder and let's make a prefab out of the arrow we can then go ahead and delete it from our scene and now we're ready to set it up in the enemy to actually spawn the arrow okay so now let's go back to our range attack state so here and then let's spawn our projectile so in our trigger attack function which is going to get triggered by our range attack we can say game object dot instantiate and remember we have to say game object dot instantiate this time because we are not inheriting from monobehaviour and to this function we're just gonna pass state data dot projectile then we want to pass our attack position dot position and then finally we want to pass it our attack position dot rotation as the rotation so now in order to be able to call this fire projectile function from our range attack state script we need to get access to it so let's come up to our variables and let's declare a protected game object that will call projectile and then that's also declare a protected projectile cold projectile script like that then it's come back to our trigger attack and we'll set projectile equal to our game object dot instantiate like that and then after that we can say projectile script equals projectile dot get components of type projectile and then finally we can say projectile script dot fire projectile and we're going to pass our state data dot projectile speed as our speed state data dot projectile travel distance as our travel distance and then finally state data dot projectile damage as our damage just like that now all that we need to do in our e to ranged attack state is set up our transitions so if we head over here get rid of this code and then make it inherit from ranged attack state we can then generate the constructor and then get the reference to our enemy too so private enemy to enemy add that to the constructor so enemy to enemy and then we can say this dot enemy equals enemy and then finally we can just generate the function overrides like that now let's go to our logic update function and then let's take a look at our finite state machine diagram so from our arrange attack state we're only going to transition to our player detected state or our look for player state so back in our script we can just say if is animation finished so our fire animation has stopped playing then if is player in min agri range then more transition to our player detected States so state machine thoughts change state to enemy dot player detected state else want to transition to our look for payer state so state machine dot change state to enemy dot look for payer state and that's all we need in here sent out let's head to our enemy to script and create the attack state so we'll have another public e to underscore ranged attack state call it range attack state range attack state create the public getter and the private setter then we need the state data so sterilized field private D underscore ranged attack state call it ranged attack state data and then we can call the constructor so range the tax stage equals a new e to underscore range the tax state this is our entity state machine is our state machine our animation boolean name is just going to be ranged attack then we pass our range attack state data as our data and then finally this as our enemy to and I forgot we also have to set up a transform for it supposed to come up here and to care another sterilized field private transform that we'll just call ranged attack position and then back in the constructor it comes after our animation boolean name so over here ranged attack position like that perfect so now let's go back to unity and set everything up as you can see we need our data and our transform so let's start off with the transform click on the alive game object and create a new empty child call it ranged attack position and then that's also navigate to our enemy to data folder and create a new data state data ranged attack state data and then we'll just call it e to underscore ranged attack state data while we're here we might as well lock the inspector and go to our prefabs folder and drag in our arrow I also see I forgot to set the projectile travel distance default variable so let's just go ahead and set that to let's say about 8 so it's gonna go 8 units before it starts falling we can then click back on our enemy to game object unlock our inspector and then drag in our ranged attack position and then also our data now let's click on our a live game object and go to our animation window and let's look at our range attack animation so here is where we shoot the arrow so we want to instantiate the arrow around here so let's just move our range attack position over there and then also while we're in the animation we need to remember to add our animation event the function we want to call is our trigger attack function and then at the end of our animation we want to add another animation event and call our finish attack animation now all we have left to do is to set up our animator so let's go to our animator window and as you can see our range attack animation is the only one we have left and let's just put that over here now we just have to add or boolean parameter which is ranged attack we can drag that up to the top and then let's make a transition from mt to our range attack click on it has exit time is false our transition duration is 0 and then the condition is range attack is true then we have a transition going back to empty as exit time is false the transition duration is 0 and the condition is that range attack is false everything should be set up now let's give it a try and see what we forgot so actually I think we need to mess with these things a little bit so let's click on our enemy to game object and let's just move it back over here so let's say when the enemies all the way over here and I stand over here I want him to detect me and shoot at me so let's click on our enemy base data and let's increase our max aggro range to about there so let's make it eight eight point five and then let's just make our min Agra distance seven point five something like that let's also make our max health 40 that way we can actually stun our enemy and then we should go to our enemy to game object again click on our player detected state data so this is how long we have to wait before he actually shoots us let's just make it one second okay let's see how it works if we jump up over here he's gonna wait a second and he should shoot us except not really because I forgot to set up the transitions like a dummy okay so if you look at the state diagram we have transitions from player detected and from our dodge state into our range attack state we also have one coming from our damage function if we are in range but we're not close so let's set those up so let's start off with our e 2 player detected state and then in our logic update function after our first if statement we want to come and say else if perform long-range action so that means our long-range action time is less than zero then state machine dot change state to enemy dot range attack state next we need to go to our eetu dodge state so in here we just want to come after our first if and say else if is player in max Agra range and not perform close range action so that means our enemy is still detecting our player but he's not close enough to punch or to dodge then we want to go into the range attack state so state machine dot change state to enemy dot range attack state now the last thing we have left to do is our damage function so let's go to our enemy to class and then in our damage function we can add an else if before our last else if saying else if check player in min aggro range then state machine dot change state to range the tax state like that okay everything should work now fingers crossed so if we get in front of him he's gonna detect us and then shoot at us perfect and then if we dodged the arrow it'll stick to the ground like that ah okay so this is why we would want to make a projectile layer so that we can put it behind our platforms but whatever works for you and now another thing I should mention is as you can see when he detects us he just gets stiff like that and that is because I forgot to add the idle animations to those animation states so in our look for players state as you can see our motion is none so that means he's just gonna show that default sprite so we can click on the little circle over here which opens up this menu then we can just go and find our enemy to idle animation and we need to do the same thing in our player detected state so their enemy to idle and that's basically it so we now have an enemy that walks around if he sees us he's gonna shoot at us if we get too close he dodges back if you get too close he punches us beautiful ok I'm so excited about this let's see if we can stun him make sure that works you get stunned and he dies everything is working so well and I'm so excited now again there's lots of things we can do to improve these enemies and I hope you guys saw how I go about adding the transitions and planning them out and things like that and I hope you guys manage to make your own transitions for your own enemies and expand upon this system there's still a lot of things I want to do the way the enemies detect the player is not always the best seeing as we're using just a single ray so sometimes if we're in front of him and we jump people no longer detect us so I'm going to experiment with using some box colliders and things like that and then when I come up with a better system of course I'm going to share it with you guys once again but for now I think we're at a good place to leave off with our more complex enemy behaviors I think it's about time we move on to some different parts of the game and then we can come back and iterate upon this later so yeah I hope you guys had fun with that now something absolutely amazing happened within the last couple of days and that is that bharden has hit 2,000 subscribers which is absolutely insane because my original goal for this channel was to hit 1,000 subscribers by the time that I graduate which is in a little less than a year and so that means I've hit double my goal with a year to spare and it's absolutely amazing and it's all because of you guys you guys have been so supportive of my work and it absolutely warms my heart and I'm so grateful to each and every one of you now I've been thinking of ways that we could celebrate this but I haven't really come up with anything good I don't really know how one goes about celebrating this but I want to do something to say thank you to you guys so if you guys have any suggestions of things that we can do to celebrate hitting 2,000 subscribers please let me know in the comments come on to discord and we can chat about it and I'm excited to hear your ideas and then yeah we'll see what we do so once again thank you to each and every single one of you I really appreciate it now before I go of course I would just like to give a huge thank you to all of my supporters and wonderful people over on patreon and an absolutely massive thank you to Gregory McHale and you Pupp for your support on patreon you guys are absolute mad lads and yeah I hope you guys all have a wonderful day
Info
Channel: Bardent
Views: 6,993
Rating: undefined out of 5
Keywords: Unity., tutorial, player, 2D, platformer, walljumping, wall sliding, jumping, Unity, Animation, ground, check, physics2d, castcirlce, variable, jump, height, Wall, Jumping, Movement, improvement, user, friendly, code, 2019, 2019.2.0f1, Ledge, climb, dead, cells, system, easy, beginner, animation, Dash, Ghosting, After, Image, After Image, Basic 2D Combat, Unity combat, Comabt, Combat, Melee, Melee Combat, Basic, Enen, Enemy, Patrol, State, Machine, respawn, hit, finite state maching, state machine, enemy, behavior, Ranged, Archer
Id: RVReK0rfzL4
Channel Id: undefined
Length: 57min 2sec (3422 seconds)
Published: Tue May 12 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.