Simple Turn-Based RPG Battle System (Unity Tutorial)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to make a turn-based battle system as used in many RPGs we're going to listen to player input when it's his turn and do a simple attack we're going to have a health system health bar damage pop ups and several other effects later we're going to take this base and expand upon it with multiple enemies special attacks items and so on let's begin [Music] hello and welcome I'm your code monkey and this channel is all about helping you learn how to make your own games with nf2 torrents made by a professional indie game developer so if you find the video helpful consider subscribing okay so this is our goal we have our player over here on the left and the enemy on the right currently the active character is the player as you can see by the selection circle being visible now it is currently waiting for player input so when I press the attack button well it's press there he goes he slides a text the enemy and slides back as you see when he was done it was the enemy's turn and he immediately did the same thing he slid to the player attacked him and then went back to his starting position and when he's done now it's back to being the players turn so we're here I can attack him again there you go attack back now it's him he attacks and he goes back we also have some nice effects I made the hits feel very satisfying so for example the blood particles and over here you can see the damage pop up the damage pop up was created in a previous video so in here we're simply going to add it and at the end as you can see we are testing for which character is still alive based on their health and we are correctly identifying a battle it is over and who was the winner all right so this is our goal a very nice simple turn-based battle system let's get to it so here we are in our empty scene let's first spawn some simple characters over here I have a prefab which contains a script at Hamill's the animations for a simple character so let's just simply drop it in here in order to see how it works there it is there is a character just standing around the code for the battle system is going to be completely separate from the animation system so you can use any animation system you want okay so we want to instantiate this prefab twice one on the left for the player and one on the right for the enemy so let's start off by making a script I won't handle our battle so in here we make a new c-sharp script let's call it our battle handler let's make a new game object to add it okay here we are in our empty script let's first spawn our characters so in order to spawn them we need the reference to our prefab so let's add it so let's add it as a serialize field so we can now go into the editor and we can drag our prefab onto the film okay now let's go into our prayer toy to start and let's instantiate both prefabs okay let's see anybody there it is one on the left side one on the right okay great so far so good we are currently spawning two different characters now instead of calling in cinch it directly and let's make a function to properly spawn our characters so we have a function where we're going to do exactly what we did previously I've been here in order to define whether it goes on my left on on the right let's just add a boolean for is player/team okay so if the character is on the planar team we spawned on the web side if it's not then respondent on the right side and now in here we just do two very simple function problems one on true and one on plus any of our characters are still being nicely spawned okay great now that we have them in position let's deal with attacks now so far we've been using just empty characters they do nothing other than stand around so first we need the a script to control our character so let's make a new C sharp script let's call it the character battle now in here we're going to add this script onto our character as you can see our character prefab now has the character battle and the character based script again the bay script is the one that handles on the basic stuff related to the animations so we don't really care how that is implemented we just care about the function that it exposes and on the character button we're going to handle all of our battle logic so let's open that script and in here the first thing we're going to do is on awake grab a reference to the character base all right we have our reference let's just test to make sure that this is working so on our private Boyd's start let's wrapping some animation so we should now see both characters playing the movement animation to the right any of their it is great so we have our main script working now let's make a setup function that the battle Handler won't call to set up some starting values so here get rid of this and make a home Lee Boyd call it setup since this is a monobehaviour attach to a prefab we can't actually make a constructor so this set of function will essentially do what a constructor would do so in this case and let's simply set different animations and textures for the player or the enemy so on our setup we receive a boolean for is player team and if he is on the player team let's go to the character base in order to play the animations related to this or to hand it on the back and if not let's have them set these sword shield animations Emma let's also modify the texture so you get the material and change the main texture and I mean here we need references for our textures so let's add them into the battle hammer so here we make a public texture 2d for the player spreadsheet and another total accessor 2d for the enemy spreadsheet ok let's drag our references in the editor here's the barrel hello and over here I have the two spreadsheets so let's write the player and the enemy okay now in order to access these public fields from our character battle we're going to make a simple static instance okay so very simple we have a private static instance and a public function to get the instance and the instance is set on awake now obviously for adding this to a full game you would handle these references more appropriately but for this in are you this won't do so we can now go back into our character battle and modify the main texture we go into the battle hammer get the instance and get the player sprite sheet and for this when you get the enemies ready all right so just like that we should now be able to set different textures and different animations depending on whether it's the player or the enemy so back in the battle handler we just need to go to where we spawn our character so we are incenting the prefab and the transform has a component of type character battle and all we do is go into the character battle and call the setup function and passing is player team all right this should be working so in here we instantiate our prefab we get the component we call the setup function and on the setup function we test if it is on the player team if so we play these animations with this texture if not this one and this one so let's see if they are both different any of their it is they have different animations and different textures okay great so we now have a very nice set of function on our character battle and we can pass in whatever films we want to make different characters now that we have them different and unique let's see only the comment so for the combat we're going to listen to your player input here on the battle Handler so let's make a private void update and for our input let's simply do input not yet key down our attack button won't be the spacebar so when we press space let's do a simple attack let's make our attack function on the character so here we make a problem boy attack now here we need to know the target we're going to attack someone let's receive a reference to the character battle for our target so this is one we want to attack so in here all we do is play the animation so go into the character base so here I can pass in the direction for the animation then some comebacks when the animation hits the target and when the animation is completed for Direction let's count like direction towards the target character battle so that means we need the position of the Atari character bounce and let's make a simple helper function simply call it get position listen you just returned the position for this character okay so we have our tech direction now one hit and let's not do anything and I'm complete let's go back to idle okay that should do it now if you're not familiar with this this is a lambda expression so in here this is essential creating a function very quickly right in here so in this case this is the same thing as this so over here and this one are the exact same thing just different representations and this one is easier to write alright so we have our attack function we receive our target we come late the direction towards the target then we play the animation using that direction and when the attack animation has completed we go back to I don't now we need to do is call this from the battle hammer so let's go in here and in order to call it we need references for our characters so right now we just have to so let's simply make a film but later we're going to store them in a list so for now make a private reference to a character battle okay so here we are setting our films when we spawn our characters and when we press space let's go into the player character panel in order to attack our enemy character back so it see if we get an attack every time we press space okay so here we are with both them I don't know I press space and there you go the player character made an attack and then went back to it I don't right so every time I press space he plays that animation and attacks okay great so far so good now one issue we have is that we can spam atack so in here if I spam space he is constantly attacking now this is meant to be a turn-based battle system so I should only be able to do one action per turn so let's go onto our battle handler script and in here and let's define some very simple states we're making in a newb to define our possible States and the postman's are either waiting for player so waiting for player input or just busy so when we start and let's say we are waiting for the player and in here on our update we're only going to listen to input if we are waiting for the player so if state if we are waiting for the player then we do only see the input if not then we don't so when we do an attack let's modify the state to be busy okay now that means we also need to know when the attack has been completed so let's set a callback to our attack function that won't be triggered when the attack is completed so over here on the attack let's add an action that will simply be on attack complete now action is a very simple delegate that is on the system namespace okay so here we do our attack when we finish we play the idle animation and then let's call our convert alright so far so good now in the battle handler we can now use that so for the comeback when the attack has been completed and let's return back into state dot waiting for player alright so we have a very simple state function we all listen to input when we are waiting for the plane as soon as we hear the space bar we set it to busy and we start playing the attack animation and we only go back to waiting for player when the attack has been completed so it should now be working for just one action per turn let's see here we are press space there you go normal tank now try the spam space and there you go I can no longer spam I have to wait for the attack being completed before I can attack again okay awesome right now for the attack obviously this doesn't look good he's attacking him there where the enemy is in there so let's make him slide towards the enemy and then he does the attack animation and then he slides back so let's go to the character battle and in here instead of playing the attack animation right away and let's do some sliding before that now in order to slide we're going to have to add our code on our update okay here we make a private void update and in here we don't want this slight code to run every time so we're going to do the same thing with it with the panel handler so go up here to find another protein you for all our possible states so here are our states either I don't sliding or a busy sorry off at I don't and then on our update we do a normal switch on our states and now here we have our sliding code on our sliding now in order to slide we're just going to modify the transform table position move it towards a certain position so that means we need a slide target position so let's go up here to define that so we have a slight target position and in here we're going to move towards that slight position okay so here we are defining a certain slide speed and we simply modify our transform dot position we come like the target Direction multiplied by the speed n time dot down to time we are not normalizing this so essentially it's going to move very quickly and then slow down which is exactly what we want so with our slide and afterwards let's make a very simple distance check we come like the distance between our position and the slide target position so it is a stiff distance between our position and slide target position if it is under our reach distance then we have arrived at our small target position all right so this is pretty much our sliding code now in order to make it easy to slide attacking slide back let's add a simple compact that won't be triggered when we arrive at our slide target position so we just go up here define another action this will be on slide complete and we're simply going to call this action when we arrive ok very simple code for our sliding we just move our position towards the target by a certain speed when we get within a certain distance we simply trigger our comeback okay now let's make a function that won't set up the necessary values the bezel in here all we need to do is set our fields and modify our state all right very simple now that we have this we can update our attack function and let's just test these slides so let's comment this out and certainly simply call slide to position let's slide exactly on top of the target so Kari get positioned and when we get there ring to trigger this action and for now let's not do anything so we should simply be able to see when we press space he's going to slide towards the target let's see okay here we are both on I don't press space and there you go he slides exactly towards the target and stops okay great now let's combine the slide with the attack so in here we essentially copy the attack code when the slide has been completed and we don't want to slide exactly on top of the target but a bit to the left of them so we complete our semi target position to be on the target then we have the vector pointing towards our position so this way we don't stand right on top of the target so we do our slide to that position then we do the attack just like we did previously except when the attack is completed we're not going to call on attack completed but instead let's slide back to our original position so we do the attack then when you finish let's slide back all right so here it is our code so first we slide to our target when we get there we play our attack animation when the attack animation has been completed we slide back to our starting position and when we are back at the starting position we go back to I don't and we trigger on that complete and I just update our stakes all right just like that so I might see if the character slice the target attacks him and goes back here we are with both them I don't let's press face there you go slide attack slide back okay great so the logic completely worked slide attack slide back right great now let's also apply the slide animations make it look better so over here let's simply play the slide animation there's a slide left in the slide right okay that should be better let's see okay here we are press space there you go he slides attack slides back and goes back to idle okay awesome now just one final thing let's see one with the idle animations so the enemy should be idling towards the player so very simple all we need is to know if it's on the player team so let's store this all right so we now have a very simple function to play the animal animation so this should help us make sure that our sprites are always facing the correct direction okay so they are both facing the correct direction press space and there you go slide the tag slide back all right great and I also can't spam space so if I attack now I have to wait and yep I can attack yet okay great so we have a very basic turn base attack working now let's make the enemy attack as well so that means giving him a turn now over here on the battle hem one essentially we need to know whose turn it is if it's a player or the enemy so let's go up here and we're going to store a character battle for the active character battle so this is the one that is active right now let's make you a function to set it okay so here we just set the active character battle now by default let's start off with the player being active so let's go in here and now let's make a function that won't choose the next active character so a private void let's call it choose next active character and since we're starting simple with just two characters this will be very easy so here we just test if the active character battle is the player character battle then we set the active to be the enemy and if not we set it to be the player and we set the state to be waiting for the player okay so this function should correctly swap between the player and the enemy now over here when the player does his attack at the end instead of going to waiting for a player we simply can't choose the next character so the player does is attack then you choose the next which won't choose the enemy and when it's the enemy's turn let's do an attack very much like the player so since they're both using the same script it's very easy we just copy this and it's the enemy attacking the player all right so that's pretty much it we start off with the player being the active character so once we are waiting for the player we listen to input as soon as we press space we do our attack when the attack is completed we choose the next active character since we are currently on the player the next one won't be the enemy the enemy won't attack the player once the enemy is finished then we choose next which won't be the player and so on so we should now be able to see first the player turn then the enemy turn okay let's see okay here we are everything is on we're waiting for player input so let's press space there you go attack back any of now the enemy attack back and now we're back to the player so press space and yep and whilst it's the enemy turn obviously I cannot attack so I have to wait for the enemy to be done and now it's my turn I know attack okay great so everything is working correctly logic for switching who is active at which turn is now currently working now let's add a visual to be able to easily see which one is currently active so for the visual let's modify our prefab and over here we can't see the character since the animation system only runs when the game is running but we can see the shadow here and under the shadow we can place our circle outline texture just a very simple texture let's tint it in green and let's call this the selection circle okay so there it is let's play just make sure both of them have the circle and you both of them have the selection circle okay great now let's make two functions to hide and show so over here on the character battle so here we're grabbing the reference ton awake for our selection circle and all we need to do in order to show and hide it is very simple we just call the game object set active in order to hide it set it to false and show it set it to true okay so we have two functions to control the visibility of our selection circle and here we just hide it by default and now let's go into our battle Handler and in here when we are setting the active character panel let's test if we have an active character down if so then we tell this one to hide its selection circle then we swap out for new one and we tell the new one to show this selection server all right so we should now be able to see which one is currently active okay there it is as you can see the player is the one currently active so press space attack back and yep now he's active and he does attack and back to me and attack and there you go and great awesome so you can now visually see which one is active in this turn so without working it's time to actually deal some damage for that we need a health system over here I have a very simple health system this was created in a previous video so check the link in the description it's pretty simple we just have the health as an integer and a bunch of functions to modify it on with some events that get triggered when something happens so let's go into our character battle and here let's create our health system so we have a feel for the health system and we create it over here on our set up and let's start them off with a hundred help okay so we have constructed our health system now let's make a function to take damage so we're here a phone avoid damage and we simply go into the whole system and caused some damage now here we need the amount and that's pretty much it now we need is to go over here on our attack admission in here we have to come back on hit and on complete so let's use the on hit this woman is triggered when the animation actually hits the target so in here we go into the target character battle to cause damage and for now let's just simply put a certain value okay so that should do it we should now be able to deal damage while attacking make sure that it's working let's add some pop-ups in here so using the code monkey CM debug class this is part of the code monkey zombies which you can grab for free from minty Kermit calm so let's simply do a text pop up saying hit and then our current help alright well let's see if we aren't correctly attacking okay so here we are now we should be able to attack him and when we do should be able to see a pop-up and since we're dealing ten amount of damage we should be able to see the pop-up saying 90 press and there you go hit and he has 90 humph left and same thing there hit him again and now he has 80 he hits me and eighty okay awesome so we have correctly added a very simple health system now that we have damage let's test when a character dies so when the character dies when it's exposed a function that won't test if the character is dead so a public boom is dead and all we do is return the health system that is dead so with this function we can go back to the panel hammer and over here we can now identify if one character is dead so when we choose the next active character let's test if the battle is over so let's make here boom test battle over this one returned true if the battle is over so we're going to call this function over here if the battle is over we return so we stop this function so we know what we select the next active if not then we continue to do it now to test if the battle is over since right now we just have the player versus the enemy this is very simple so if the player character battle is dead the player is dead and the enemy wins if the enemies add then the enemy is dead and the player wins in either case the battle is over and if neither of these then the battle is not over all right that should do it let's add some puppets for testing no it's s if it's working so over here let's increase the amount of damage here on let's hit him and with 40 damage he now has 60 now get him again now he has 20 and I when I hit him he's going to die let's he hit him and the player wins and as you saw he didn't do his attack since he's essentially dead alright so Omar logic is working correctly now let's make it a little proper so for starters let's make a health bar instead of a debug pop-up so over here on the character battle on our setup we can use a very useful and warm bar from the code monkey toys which again can wear up for free from in Tacoma comm I've done several videos where I cover how to make a health bar so check those out to understand how they work it's pretty simple so in here we're just going to use the one from the utilities okay we should be able to see a bar on top of our characters and if there it is now let's update our bar now in order to update them let's first store a reference to our wine bar and then on the Health System we have some events that trigger when the health changes so we can just subscribe to those so on health change the event let's subscribe to that and when the health changes we just update a hump bar so we set size and we ask the health system to get the health percentage all right let you do it for the hump bar so let's take away our debug pop-ups in here and let's just test if there it is both numb with a thumb farm let's attack and there you go the health bar went down and yep just like that okay great now when the character dies and let's have them lying on four so here when he takes damage let's ask if the health system is dead then this character died we just played the correct animation let's test okay here it is he's going to die on this hit so hit him and there you go he's lying on the floor and the player wins great now for another effect let's have the damage pop ups okay here it is the damage Pappas folder this was created in a previous video so check that out to see how it was done in order to use it it's a very simple function call so here on the damage simply go to the damage pop-up and create a pop-up right here with this damaged amount okay you're on let's hit him and there you go a nice damaged pop-up and same thing on him now let's randomize our attack so the number isn't exactly the same every time seen here on let's define in for damage amount so we now have more variation on the damage and if there is we've got nice damage problems okay great now for another effect let's add a nice damage tint okay here we are and hit him and you better go a nice tint now for some nice bought particles so in here to know the direction of the particles we also need to know who attacked them so let's bet in here another character bottom for the attacker okay here we are let's hit him and you're gonna give some nice what particles happen right there now I haven't done a video on the particle system yet so let me know if that's something you would like to see it essentially just creates and updates a dynamic mesh let's also add some screen shake on hit and there it is a nice screen shake when he gets hit okay great and finally let's make a simple bottle over window all right here it is a script very simple we just have a static instance so we can have a static function and we simply pass in a winter strength so on the about hem one over here when you test instead of doing a puffle let's use that alright let you do it okay here we are let's see who wins so attack and there you go there's all of our nice effects now keep attacking the attacks are now randomized on the damage amount so let's see if I win and no no he hits me and nope and I hit him and yep I win and there you go bottle over player wins okay awesome so over here we have our very simple but also very nice turn-based battle system we start off with the player's turn as you can see by the select circle so we're currently waiting for a player input and I can hit space to do an attack and there you go he slides towards the enemy attacks him and goes back when he finishes it's the enemy's turn and as he saw his smile it's worthy player attacks him and goes back both characters are using the same script so all the effects and everything works flawlessly when the enemy is done he goes back to there and now again as you can see by the selection it's a player again and now I can hit him again and there you go go back now it's him and yep now attack him again and he's still alive now he kills me and there you go battle over enemy wins so we are correctly identifying when the battle is over and who was the winner now in the next video we're going to take this base and expand upon it with multiple enemies special attacks items and so on so make sure you understand how this base works and stay tuned for the next video as always you can download the project files in Italy's community code monkey comm if you liked the video subscribe the channel for more unity tutorial post any questions you have in the comments and I'll do my best Internet alright see you next time [Music]
Info
Channel: Code Monkey
Views: 120,502
Rating: undefined out of 5
Keywords: unity turn based game, unity turn based combat, unity turn based rpg tutorial, unity turn based game tutorial, unity rpg turn based, unity turn based rpg 2d, unity rpg 2d, unity turn system, unity rpg game, unity rpg, unity rpg tutorial, unity rpg tutorial 2d, code monkey, brackeys, unity tutorial, unity game tutorial, unity tutorial for beginners, unity 2d tutorial, unity 3d, unity 3d tutorials, unity tutorial 2d, unity2d, unity3d, unity
Id: 0QU0yV0CYT4
Channel Id: undefined
Length: 35min 22sec (2122 seconds)
Published: Fri Jul 05 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.