Grid Combat System! (Turn-Based, XCOM)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to make a turn-based grid combat system in unity our units will be in two teams placed in a grid with a certain move radius and the ability to do attacks each units won't do its move and then its attack in a turn-by-turn bastes 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 NF tutorials made by a professional indie game developer so if you find the video helpful consider subscribing okay so here's what we want to make over here we have a nice map with a bunch of characters so these are on the blue team and these are on the red team now it's turn-based so right now the active turn is for this unit on the grid we can visually see how far he can move so I can click on any of these valid grid positions I click any of there you go he moves towards it now for each turn I can do one movement and one attack so over here is an enemy and I can click on him to attack so if I click yep there you go it does an attack and now for this system I went to the design of one character at a time rather than one phone teamed and one full team so as soon as the character on the pool team finished it picked a character from the red team so now it's this one and again I can see how far I can move note how the movement is using pathfinding so because this creighton here is walking I cannot actually reach that position but again I can move anywhere that I want so let's go all the way up there and now I can attack so let's attack that one and yep there you go now it's back into the blue team and again I can move and now that one is too far so I cannot attack him so I can press space in order to skip my turn and now it's back into this one and now this one I can try moving in there now try hitting him and no piece too far so now skip again and so on and so forth so here is a base for a nice turn-based great combat system everything is functional and we couldn't later expand upon this with some special abilities and some AI for the enemies to make a game pretty much like X huh right now there's a spring sale happening on the assets or turns of great assets icons sound effects and awesome tools at a great discount use them to make your game really stand out check it out by clicking the link in the description and if you pick up anything through there you'll also be helping out the channel alright so this circle let's get to it okay so here's our starting scene we have a map with some units and some objects now the map is built using the grid system that we made in a previous video so I can turn on gizmos and visualize the grid I'm also using the pathfinding which again was also made in another video and I'm also using the town map which we're going to use to display our reach about areas so if you haven't seen those videos then check the links in the description this combat system won't be built on top of those which once again is a great showcase of the power of writing clean code so we made that grid system a long time ago and we've reused it in so many different scenarios because we made sure to write our code in a clean and reusable way here in the editor there's a simple game object and has this script attached to it so this is a script that is setting up the grid the path finding and eat Alma here is the script and it's pretty simple we just define a certain map weight and map height then we construct our grid our grid pathfinding and our movement town map so with those systems in place we have our nice base this video is made possible thanks to these awesome supporters go to patreon.com/scishow to code monkey to get some perks and help keep the videos free for everyone now let's make our grid combat system we're going to first work with a single unit and give it a simple move order so in the project funds let's create an EC JavaScript call this our grid combat system let's make a game object to run it and attach our script okay now in here let's first make a field to add our unit reference so we make a sterilized film of type unit for it combat we're going to see how that class is set up in a bit so we have film for a unit and back in the editor over here we can now simply drag our reference okay so first of all let's make some simple movements sending a unit to a target position now each unit is based off of this prefab here so the end has a main unit great combat script and the rest of the end of the setup like we did in the modular character controller system so it has a bunch of modules like this one here which moves the unit towards a target position using plat finding and this one is moving to unity by modifying the rigidbody velocity but essentially for the logic of our combat system all we need is the main script in here and this script is already set up to interact with all the rest so in our unit great combat script on we really care about right now is the ability to call this function so we moved to a Terry position and we have a comeback alright so let's go back into our main script here we are and let's do a simple voi update and on the update let's test for left mouse button play so when the left mouse button is down in here and let's grab the mouse wrong position so for that there's a function in the utilities which is long as you can download for free from me in Tacoma com so I can go into the Tonys to get the mods wrong position here is the function in case you want to write it yourself now with the mouse wrong position let's down the unit to go there so going to the unit credit combat and we use that function we saw tell me to move to the target Mouser opposition all right so just like this it should work let's test okay here we are with all the units idle and now I move my mouse and I press the unlit mouse button any of there you go the unit correctly went into that position and now if I click behind that crate and yep there you go as you can see it is indeed using path line alright so we have our basic movement working awesome now one of the main things that we want to apply to our combat system is to have some limited movement so the unit cannot for example move an Internet month so I cannot come in there and he should not be able to move this whole distance so back in our code here let's calculate all the valid positions that unit can actually move to now the way we're going to do that is to come late the path to each position and then we're going to check the length of that path so let's write that code on our start and for testing let's start off small so let's say our unit can only move at most five steps and now in here we want to test all the positions within that radius so first we get the unit and we access its position but now we don't want the worm position but rather its position on the grid so for that we need to access the grid again the grid is being set up in this script so it's in here and it's being constructed in here and we already have a nice simple function to return that grid so let's access this function so we go into that script access the static instance and get our grid so using the grid we can access the function in order to get the x and y position of a certain world position so we get the unit ex in the unit wine now with the units x and y we can simply do a basic cycle so we do a four we start off with the X start off at unit X minus Emacs move distance and we're going to go until the X is under unit X plus D max move distance and do the same thing for the Y alright so here we are cycling through all the grid positions there are around our unit position within a certain maximum distance now first let's check if this position is walkable so for that we need to access the tough finding grid so the position is either walkable or not walkable now if it is well cable then let's complete the path to that position so if there is a valid path then we get the actual path test account so if we get the path we calculate the path count towards the maximum distance and it's either within the move distance or it's outside our move distance so if it's in here then it's valid if it's any of these others then it's invalid all right so our logic should be working now in order to visually see it we can use the town map now here in the actor I've already set up my town map it's prepared using two towel types so there's none which is invisible and move which means we can move towards it over here we can use that we get the movement on map and we set this town map sprite and we get this X and this Y in this case set it to move and all the others we set it to invisible all right so just like this everything should be working we should be able to visually see all the great positions that we can move to and all the ones we can't all right so let's test any up right away we can see that our logic is indeed working so we can see which valid positions we can move to and we can see which ones are within our max range of five of our actual unit now let's just verify that everything is actually working correctly so here let's place some more crates and if there it is just like that we can see that it is indeed working so these crates are plugging so we can no longer move to this area all right so we can now validate all of our possible move positions awesome now we need to make sure that we can only actually move towards the valley move position because right now visually we can see it but I can self like in here and Yap he goes in there so let's do just that now one of the best things that we added when we made our grid system was the ability to make it work with generics so each grid position has a grid object of a specific type now so far we've been using this empty word object so really just stores the create the X&Y and then we're doing some debug drawn lines so we can visually see the grid now let's replace this with a proper grid object to store all the data that we want so let's copy this class then let's go into the combat system and then you know let's create it all right so we have our basic red object in here and now we need to do over here is modify the type instead of using this time let's use the one on the grid combat system all right everything is working correctly and now in this grid object well it's all of the data that we're going to need so for example let's have one a simple private ball for is Valley blue position and some functions is set it all right we have our simple bullion and now all the way appear when we are completing our valid positions if it is valid then we go into our grid in order to get the grid object on this X Y and we call our set function and in this case this one is true and then on the other case it's false so let's do that up here okay so we set them all as invalid then we go through and the ones that are valid we set them to Val so now that we have validated our move positions let's go down here on our unit grid combat instead of moving it directly to there let's first validate that position so we access our grid we have the grid object on the mouse wheel on position we check if it is a valid move position and if so then we do tell our unit to move towards that position okay so just like this it should be working let's test so here we are let's try clicking in an invalid position so out here I click and nope nothing happens the unit does not move now I click in a valid position any of there we go he goes towards that position all right so our logic is working awesome so here we have our grid movement being correctly validated except right now we're only calculating it on start so as my unit moves it should update the actual newfound position so let's do just that first we take all this code and we actually make it into a proper function so instead of being on the start so we have our update from with move positions function and then on our start we call that function and now here on our update we need to call it also when the unit reaches its position and we should also block our movement once the unit is actually moving so for that let's make a simple state machine just like we did in the enemy AI video all right so we have a simple I known for our state and if you want to store that then on a weekly serif as its state dot normal and on update we do is switch on our state if we are normal then don't listen to inputs and if we are on waiting then we are simply waiting so now I mean here when we turn to move let's modify the state and in this case we're going to put it state waiting and then this move to function already has a comeback that gets called when the unit reaches its position it's just a simple action don't get I cover delegates in another video if you want to learn more but essentially this function won't get triggered at the end so it's in here that we can reset the state back into state dot normal and after resetting the state then we can update our valid move positions all right so that should do it let's test ok so here we are and we can see all of our move positions now let's move down here and wait any of the Rio s and this gets there now he updates now I can move to these positions so let's go in here and yep it updates and now I can go in here and there you go now the validation is working so I click out here and nope it does not go anywhere so clean there and yep there he goes all right so everything is working awesome so we already have quite a lot of our system we already have our unit moving in a grid and it's moving in a turn-by-turn basis so after I move I cannot click anywhere I have to wait for the unit to get there and only then can I actually move again so our turn logic is already working and while so validating just how far you can move so I cannot move this unit all the way appear only into the valid move positions so without working now let's set up our attacking so we want to be able to click on an enemy in order to attack him if he is within range so first let's handle clicking on it now one way we can do that is using colliders and great casts in order to choose the enemy to attack however using that approach would mean that the collider size would have to perfectly match the annoying grid size so instead of colliders and Ray casts a simpler way we can do is simply store our unit on the grid object itself so here in the grid object that we made we can simply add another field and this will be a film for the unit that is actually standing on this grid object so we add of time quit combat and it's UniCredit combat that is on top of this great object and now some function to set and get alright so we have our field and then a function to set a function to clear and a function to get it so now we need to initialize this so let's go all the way up here and we're going to add another serialize field and this won't be an array of our unit for combat and now let's go into the editor and in here let's drag all of our unit references okay there they are and now in here on our start let's update all of our grid objects so let's second through it so we cycle through all of our units and we get the grill get the grid object on that units position and we set that field okay so now down here we can check when we click on a unit position so we get our grid then we get the grid object underneath the mouse and then we check if there is a unit inside of that grid object if so then that means we have clicked on top of the unit then we test if the target unit is an enemy to the current one so we clicked on an enemy of the current unit and if so then we want to attack him so we tell the this unit in order to attack the other unit and again the attack also has a delegate that triggers on the attack complete so we can do the same thing to modify our state so he attacks a target in it then he goes back to normal and then we have our not an enemy and not a unit here so if we attack then we break and if not then we keep going down here and we test for simple movement all right so just like this should be working so if we click on an enemy we should be able to attack him let's test ok so here we are and if I click outside move area no cannot move I click yep I still got some right more movement now if I click on top an enemy if there you go he correctly attacks the enemy and effect me I'm talking to himself nope doesn't do anything click on top of and mi and nope does not do anything alright so I can now click on an enemy in order to attack him great now we still have a few things to note so first it's we also need to validate the attack range so right now this one is very far but I can still click in order to attack him and when we move we need to actually update the underlying grid object since right now I've moved this unit but the underlying grid object so has this unit placed on its actual starting position so let's do both notes first for the attack we just need to use the function that checks if it can attack so if this unit that can attack the target unit so you can either attack or cannot attack and this function is wrong just doing a basic vector three distance and in here if we cannot attack and let's spawn a simple pop-up all right that should do it and now for updating the grid down here when we have a valid move position what we're going to do is remove them from the current position so we go into the bread we get the grid object of this unit and then we clear that in acrid combat then we take the target grid object and then we set the unified combat to this one all right so that's it let's see if our attack is working ok here we are know the attack distance is pretty much the same as the move distance so if I come like he should not attack so quick and nope cannot attack ok great now if I move close to him and I four click yep there you go now I can indeed attack him so I can move into a random position and click any of there you go everything is validated all right so here we have movement and attacking working awesome so here we have our system almost fully built everything is working perfectly except it's only working for a single unit so the very important thing that we are missing is our turn system now I already covered a simple turn-based battle system in a this video so here let's do something pretty similar over here in our grid combat system we already have a nice array of one of our units now what we need is to have them split into two teams and go from one team to the next one so let's make some simple two lists so we've got Blue Team and Red Team now in here when we are cycling through them we can do that as well all right so very simple we just initialize our own list we cycle through and we add them depending on the team they're in now up here we're also going to need some indexes in order to figure out which one is our active unit and we start them both off at minus one okay now let's make a function to select the next active units so first we check the team on the current active one so if the current one is either no or it's on the red team then we get the next one on the blue team and if now we get the next one on the right team so let's make that function alright so we get the next active one of this team so we just increment our index and then we return that one on that position and then here when we select we set the unit quick combat to be done alright so all of our logic should be working so the first time that we call this this one won't be known so it's going to pick one from the blue team then next time we call then this one will be on the blue team so we're going to pick one from the red team and then so on and so on so we have this function to correctly pick the next active character and now most of the rest of the code already works using this field so everything else should be working so we just need to calm this so peer on our start we set everything and before we update our available positions well it's not like the next active unit and up here and let's no longer expose this in the editor since it's going to start off as no okay that should do it now for testing let's make them swap after just moving once per turn so down here we have our movement okay and after the end finish is moving then let's some like the next active Vienna okay let's test and here we are in it's this one's turn someone let's move in here and yep as he gets there now it's this one's turn and again everything is being validated so I click all the way in here nope nothing's now let's move that one in here and yep that was the red team and I expected the only team so the blue team move and the red team move all right so all the logic is working and all of the terms are correctly moving now that our logic is working let's make them move and attack on the same turn so in here we can just store two simple billions when we saw like the next active one let's set both these to true and down here we found a time all right so we found a team move any attack and now just say function to test if the turn is over so if we cannot move or attack then we end this turn and we're going to do our test every time that we move or attack so we can also use this function in order to skip the turn so here on our update let's also do a simple input yet key down when you press space then let's give our turn all right everything should be working let's test so here we are in start off with this yep so far so good let's try moving in there and yep he moves now let's try attacking and if there you an attack you know it's this one so now this one I can first attack and then I move and since I finished now it's this one so now this one moves and now I try to attack but I cannot because he's too far so I can press space and if there you go I skip the turn and now it's this one and now this one can move and now let's attack this one and so on and so forth all right awesome so all of our turn logic and all of our combat logic is correctly working now for just some punch in here I already have implemented camera panning so I can press the way s and E in order to move the camera so that one is being handled using Sen machine now I covered how to use sin machine in a previous video so check it out if you don't know how to use it again it's being handled by our normal game handler script we have our handle camera movement and then we have a nice function in order to set the camera fall position so just for Polish let's call this one whenever our turn changes so here when the turn is over let's go where we select the next active unit and after selecting let's go into our game Handler and call this function to pan the camera onto our unit all right just like that let's see okay here we are let's move this one in here and now let's skip and if there go the camera pen so that one now I can move it can skip any up pencil down and so on alright so here we have just a bit of nice polish okay so here we have our system fully working we have two teams the blue team and the red team now each unit can move an attack in its own turn and I can also skip a turn if I want so I can move this unit then I can do an attack and after the attack is finished then now it's a red team's turn so now I can move an attack and there you go now it's backing to the blue team so they change between the red team and the blue team now for the movement you can see the event positions that we can move to all the positions are accumulated using pathfinding so we can only move to valid positions so here this crate is walking so I cannot go into that position so I can click on a valid position move in there and now click in order to attack an enemy and now the attack right now we set up to always hit but we could easily add some sort of hit chance based on distance in flanking in order to make this pretty much like X huh so you can click to move click to attack and if there you go as soon as it ends it ends its turn now I can again move an attack and so on now right now something that could be a performance bottleneck is how we calculate all of the possible paths that the unit can take so depending on how far your units can move this can be quite costly or not as much now one way we can easily solve that is to use the path finding that we made using unity dots that one if you remember works thousands of times faster than this one so if you wanted to build upon this system then that's one of the things that you could actually improve beyond that here is a fully functioning turn-based great combat system let me know in the comments if you'd like to see me expand upon this to make a complete game like Exxon this video is made possible thanks to these awesome supporters go to patreon.com/scishow code monkey to get some perks and help keep the videos free for everyone as always you can download the project found a little is from unity comic calm subscribe the channel for more unity tutorials push the nuclear 7 accounts and I'll see you next time [Music]
Info
Channel: Code Monkey
Views: 71,027
Rating: undefined out of 5
Keywords: unity turn based combat, unity turn based battle system, unity turn based movement, unity xcom tutorial, unity grid movement, unity turn based, unity xcom movement, unity xcom, xcom, code monkey, brackeys, unity tutorial, unity game tutorial, unity 2d tutorial, unity 3d, unity, game design, game development, game dev, game development unity, unity 2d, unity 3d tutorial, programming, c#, code, software development, learn to code, learn programming, xcom chimera squad
Id: mONHucoYASU
Channel Id: undefined
Length: 26min 35sec (1595 seconds)
Published: Fri Apr 24 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.