Cool Heatmap in Unity

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to make a heat map to help display information to the player we're going to expand upon the grid map we made in the previous video and use a custom mesh to dynamically update our heat map 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 here we are and this is what we want to make we have a nice scene here and looks like it's completely empty and just with a applied texture however when I click on the mouse yep there it is I play something which modified the underlying grid and divisional display so I can click with the mouse button in order to impact the underlying grid which then impacts the visual and as you can see the visual where it's clicked it's red and as it gets towards the edges it becomes red and where the value is zero it becomes black so the color is smoothly interpolated based on whatever value is underneath now I have enable debug visuals so we can see the underlying shape and families of the grid and you can see that when I click the valley's change individual also changes so right down the middle you can see that it has 100 which is the maximum value as it gets towards the edges it continually goes down until it reaches zero an example of something like this used in a complete game is the park environment system in battle morale pack unit in the game you can place objects to improve the park environment and each of them has a radius and an effect they cost so when I place an object the environment updates and increases the underlying value in a nice diamond pattern so this is an example of a system like this being used in a final game all right so this is our goal let's get to it ok so here we are in our scene where we have just a simple background texture also in here on the scripts folder I have the grid class that we created in a previous grid map video if you haven't seen that one yet there's a link in the description in that video we go through the creation of the grid class which we are now going to use as a base to create our heat map the grid class is already based on ends which is exactly what we want to use here so making this effect should be relatively simple so let's first start off by making sure our grid class works so we're going to create a new script let's call it testing and here make a new game object call it testing and drag the script onto it ok now in here let's make a privately start and in here let's create a grip so we do bread make a new grid passing the width and the height so let's pass in with a 20 height of 10 now we pass in the cell size let's say 10 and the origin let's put it at vector 3.0 all right so let's see what this does and here we are and yep there it is our full grid map with a width of 20 and a height of 10 right awesome we have text objects being created which show the underlying values and using gizmos we are enabling to show the edges of each grid so again all this was fully created from scratch in a previous video so check that out if you haven't already all right now that we can see our starting grid let's think about what we're going to need in order to make our heat map the first thing we want is make sure our grids underlying value stay inside a valid range so let's go into our grid class here it is now we have our simple constructor which is you can see we receive with height a cell size and the origin position then over here we have the code to show our debug lines and text fields and if we go all the way down here we have our nice set value function so it's here that we want to validate this value to make sure it says within our valid range so for that let's make some constants go all the way up here make a public Const int and let's call this the heat map max Valley Ana let's put a maximum of 100 and a public content for our heat map min value which will be at 0 and now we just take these and go down to the set value and let's make sure that our value is math F climb so we're going to clamp our value between our minimum and our maximum all right that should do it so let's go back into our testing script and in here let's make some code to increase the underlying on the grid whenever we click on so make a simple update and here we test for an input yet mouse button down on the left mouse but and when they do let's get the mouse wrong position so for that I'm going to be using the cosmic utilities she as always you can grab for free from in Tacoma comm so from that I can use get Mao's world position here is the function in case you want to make it yourself oh it does is a screen to one point on our world camera so with our mouse world position we want to increase the annoying value of the brain so before we set the value let's first go in the grid and get me down so in here we need a reference to our grid object so we have our reference we set it on start in here we use in so we get the value passing the world position alright this is our current value then we do read that set value pass in the same position and then we pass in value plus five so every time we click we should be able to see the underlying value increase by five alright let's test okay here we are in our grid now first of all if we click outside the grid you can see that nothing happens in the previous video we decided it was best to ignore invalid values in order to prevent our weight from behaving weirdly over on the edges so factly here does nothing but if I click on top of the grid there give that one went from zero to five come again 10 and now keep clicking and let's see the maximum and there you go it's at 100 and can no longer go higher okay awesome alright so now that the underlying values are working correctly let's see how we're going to display them with some very nice colors so that means it's time to work on our heat map visual so in here what's our off by making a new C sharp script call it heat map Viggo let's make a game object to handle it so when you game object code the heat map visual drag the script onto it and let's make sure the object is on the origin so 0 0 0 okay now let's open it and now in here in order to display our heat map we're going to use a custom dynamic mesh if you want a in-depth look into how to create a dynamic mesh through code then check the link in the description in that video I cover what are the elements and mesh needs and what each of them represents it covers how to start off rendering simple triangle then making it into a quad and manipulating the texture if you understand everything in that video you'll be able to easily follow along how we're going to create the heatmap visual mesh okay so let's create the mesh and for that I have a simple mesh utils class this has a bunch of functions for creating and adding stuff to the mesh you can easily make this class yourself based on the knowledge of the mesh video or you can download it from this videos project funds it just creates the various vertices UV strangles and has a bunch of functions for setting them again if you're not familiar with how much is created through code check out the other video linked in the description now in order to render our mesh there's still something we need on our game object in here which is we need to add a mesh filter and also a mesh renderer so this mesh will be created dynamically through code and now in here we need to add our material so here in the project files you can see that I have a nice gradient texture as you can see the first pixel is black then it goes from red to yellow to green so let's make a material to use it just very simple make a new material let's use the unlit texture and drag the texture onto it alright there's our material and just drag it onto our mesh render all right that's it now back in the code now here in order to visualize our heat map we want to display one quad per grid position so first we need a reference to our grid so let's make a function a polaroid call it set grid are going to receive a query object let's store all right so now we need to call this function from somewhere so for that let's use our testing class and here let's add a serialized field make it a private type eat map visual and on start first we create our grid and then we go into the heat map visual and set the grid and passing our grid all right so now we just need to go into the editor and here on the testing script let's just drag the reference all right awesome so back into the heat map code let's also make a wake to grab the reference to the mesh filter so we have the reference to the mesh filter and we need to set our mesh so in here let's make a mesh equals a new mesh so this is the mesh that we're going to use and reuse so it's actually stored up here just like that all right so our setup is done in order to visually see our mesh now it's time to finally make the code in order to actually draw it so down here let's make a private road and let's call it update the heat map video now here let's first set up our erase here on the mesh utils I have a nice function which already calculates on with the vertices UVs and triangles with a given quad count so let's use that so go into the mesh utils count create empty mesh arrays now for the quad count it's very simple we just need the grid in order to get the width multiply it by the bracket height so that's our quad count and now let's create our race all right so just like this we are creating on with our local arrays with the correct size now down here let's cycle through the width and the height all right here we are inside our cycle and now in here let's first calculate the index that we are currently on so a name for our index and the current index will be the current X multiplied by the grid get height and pause the current one so with this we have our index cycling through every single quad so much used to debug down one to make sure everything is great so far so debug dialog on our index and in here when we set the grid what's called update the heat map video and to make it easier let's go in here and reduce the size to be just ten five all right let's test and here we are and there's our small grid and over here on the console we can see our indexes are need going correctly so going from 0 all the way to 49 since we have 10 by 5 right awesome now in here inside our cycle we already have the index and it's in here that we need to set our quad valves so for that I have a very nice home phone function here it's called add to measure race and just takes the various arrays that make up the mesh takes an index and locates the new quad so let's use that call add to mesh race let's pass in the vertices the UV and the triangles now for an index pass in our calculated index and now here we need the position so for the position we can just go to the grid and ask for the get world position of this given x and y alright for the rotation we don't want any rotation its own let's leave it at 0 and now here we need the size of the quad so let's calculate it up here a factor 3 for the quad size and the font size is really just let's make it a vector 3 of 1 1 and multiply it by the grid and get the cell size right just like that and now finally we need UV and for now let's just leave it at 0 so all our points should be completely black over here on awake we are creating our mesh then on this function we are creating the empty mesh rays with a given width and height then we cycle through every single grid position and we add a quad to our mesh race so all that's left is to go down here and update our mesh all right that should do it let's test and see if we are correctly creating our black mesh and if there is there's our grid mesh we can pause in order to go and look into the wireframe and let's hide the background so we can easily see it and if there you go there it is we can easily see every quad of our grid mesh being in sentient awesome however you can also see an issue with the mesh the quads are on the origin of each sound position instead of being right down the middle so we need to shift them all by half of our cell size so let's do that it's very simple just in here we get the quad position and we just increase it by the quad size multiplied by 0.5 okay test again any of there it is and all of our quads now perfectly match with our underlying grid great okay so now the visual is setup however if I click the modify it you can see the underlying value change but the caller didn't so we need to update our visual when something changes so we're here in the grid code you can see that right in here there is a nice event and as the name implies this is fired right when some value under great changes so there it is down here on the set value you can see we set the value and then we fire this event so we can easily go back into our visual and when we receive the grid let's simply subscribe to that event so grid on Great Valley changed let's subscribe to that event and when that event is fired we simply update our equipment and that should do it very simple and this clearly shows you the power of events so let's just add a debug want to make sure our event is firing just like this okay let's see ok here we are let's click and see if the event is fired click any of there you go over here on the console you can see the event spark click here and yep yep yep yep okay awesome so we are correctly capturing our unfairly changed event so now almost everything is set up we just need to deal with the UV for the quads to match the underlying them so again here is the underlying texture it's a simple texture with 64 pixels on the width and one on the height now we want the color shown to match the underlying value so with a value of 0 we want to show the black pics on right on the left and with a value of 100 we want to show the green pics on right on the right so let's go to our code and in here inside our saikhan let's calculate the UV nor do that first we need to know the underlying value so go into the grid in order to get the value let's get the value on the current X&Y all right this is our grid value now again the UV is always set with a normalized value so in order to comment like that we need to define the current by the maximum so we get our float great value normalize and we essentially just take our great value and we defined it by our maximum Park we'd hit max max Val and these are two ends so again in order to make sure we don't get any mistakes we need to convert one of them into a fault all right so here we have our normalized value and with this we can now create our UV vector too so in vector 2 for the grid value UV and it's simply going to be on the X we pass in the great value normalized and under why it doesn't matter so let's just put it at zero so then here on this function we have actually two UV fields we have one on the lower left corner and one for the UV on the upper right corner however in this case we just want to show pretty much a single pixel so it doesn't matter let's just put the exact same one on both so every single vector won't show the exact same pixel all right so just like this it should be working let's see okay here we are and everything is black all right now let's click and there you go that one went from black to a dark red now keep clicking and starts becoming more as it reaches 15 it's pure yellow now keep clicking and snow green green green and yep now it's at 100 pure green right awesome so as the valley goes up so does the color go from red to yellow to green so now we can set and view families in our heat map now in order to achieve a nice heat map we should make sure that when we click we apply more than just on a single grid position so in this case we wouldn't like if this one is at 52 also impact the ones around it okay so let's make a function to add a value to our grid map along with a certain range so let's go into our grid here we have our set values and get valid functions now let's make a add value we're going to receive a vector3 for the world position then we're going to receive an end for the target value to add and let's also receive an end for a range so here on let's start off very simple first we get the X&Y now we just cycle through the entire range and in here we want to add the Val however right now we only have a function to set the value so let's make another nice helper function and this will be the add value it takes it in for the X and for the Y and then in for the event and here in order to add it's very simple we just call get value on the x and y that gives us our current value so we increase it by our target value and we put all this inside a set bump okay so there it is a very nice simple function it takes the current value and increases it by this amount okay now we can go down here and use it so we set on through the entire range and we call add value on this X so origin X was this X and we add our valid all right this should be working let's test it so for that let's go into our testing class and in here we were doing pretty much the same add value however instead of that let's do the grid add value we're going to use the version that has the range so passing the physician let's put a value of five and a range of also five and up here let's make our grid bigger but with smaller notes alright let's test this okay here it is let's move all the way here now let's click right in here and there you go we now have a bunch of cells with five and if we click again and there we go with these ones that were in the middle they increase by five so now they have ten all right so we have our nice heat map correctly working however the shape that we're using is a square which isn't very nice we want a diamond instead so let's see how we're using the range over here on our grid we're cycling through the x and y both going from zero to the range but instead of a square we want a diamond so let's first make a triangle since the diamond is essentially just four triangles put together so we're here we are cycling through everything except on the Y cycle instead of going from zero to the range let's go to zero to the range minus the X so this way the bigger the X is then lower dy I won't go let's test okay here we are let's go and click right down the middle and there you go we now have a very nice triangle with a edge size of fine all right awesome now to make a diamond all we need to do is mirror this triangle both left and down so first let's mirror to the left so we also call that value seven set of heading on origin plus X we add on origin minus X okay click and there you go we added on the right and on the left side however you can also see that we doubled on the first line so we need to ignore that and here we only do this if the X is not zero and if there is now we have a right and left triangle okay great now for the lower side we do pretty much the same thing we do add value on the origin Y minus ey and the same thing on minus X and minus y so let's see okay click and there you go alright the shape is correct now let's just ignore these zeros so you only do the wise if dy is not zero and on the minus X once again you just if DX is not zero okay here we are now let's try right here down the middle and click and there you go we have our nice awesome grid and by clicking we add the value in a diamond pattern and if we click again you can see that we add the value where we already had them so if I click in here there you go these there are in between they also increase so I can add various and the color all looks very nice so let's try this out without our debug so go into the grid and over here just have the show debugging to false and there it is now we just see a giant black square and if we click if there you go there's our nice heat map showing all our nice colors so as we increase it goes up and now that one is green red and so on all right awesome now our heat map is pretty much done let's just add one more thing a version that takes a range and then the family falls off as it gets towards the end range so down here on the grid we have this function alright that looks right however now let's split the range into two different values so we're going first to have a full value range so this is range where the entire phone value is added and then we also have an end for the total range so when we go past the phone value range we are going to decrease the value until we reach Ito range okay so let's first calculate the amount we're going to lower the value once we go past the phone value range okay so we commonly the lower value amount by the difference between the total range and the phone value range now over here in the cycle we're going to cycle through the total range okay so then here inside our cycle let's first calculate where we are on the current radius so when in for the radius is simply the X plus zy then let's also define the value amount that we're going to add so it's called the add value amount and by default we start off with the full volume then we test if the radius is bigger than the full value range if so then we want to decrease the add value amount by the in lower value amount so we're going to add value amount minus equals the lower value amount multiplied by how far we are from the total so the radius minus our phone value range so as we get past the phone value range and towards the totem range it will go down down down so visually as we approach the edge of our radius we should be able to see the center in green and becoming more red towards the edges and down here instead of the value we use the add value amount which has been calculated all right great now here let's test it with a really big radius so first on the value let's put the full value to be a 100 and for the full value range and let's put something sponson like five and for the total range let's put 48 so for the first five positions around where I click it will have a hundred and for the rest until it hits 40 it won't constantly be going down so we should be able to see a diamond pattern start with green in the center and become red towards the edges okay so to test let's make our grid a lot bigger okay so here we are and everything is black meaning all of our grid is at zero and now let's click and there yo there's our awesome color diamond pattern and if I click somewhere else like right here on the right and the radius intersects you don't be able to see any of there you go over here where they both intersect you can see that both valleys are being added so when I clicked here the positions that include both diamonds also increase their underlying values so here we are with the debug visuals enabled and now we can see how the numbers change so let's click in here and there you go you can see right down the middle it's at 100 so it's full and as we go towards the edge you can see the number constantly going down and then if I click here on the side yep you can see it goes down but these have been merged by both times so click on various sizes and there you go you can see the heat map getting very nice there it is all our nice numbers awesome now just one final thing over here we have a pretty serious performance issue in our code that we can easily solve over here on the heatmap visual we are updating our heat map visual whenever this event is fired and then here on the grid when we are creating our diamond pattern we are essentially calling add value a whole bunch of times and every time we add we are triggering that event so every time we trigger we are updating the mesh so essentially when we place we are updating our mesh about a hundred times in a single frame that is obviously very wasteful and causes your game to hang for quite a bit so instead let's only update at the end of each frame where the underlying grid did actually change so let's go up here make a private a boolean con like update mesh then we go down here when the grid value changes instead of calling this directly let's simply set the update mesh in to true and then we're going to have a private void and light update and in here we test if the update mesh is true then we set it to false and we update our mesh so just like that no matter how many times this event is fired in the same frame it will only update once at the end of that frame and if this change it doesn't update so everything is great alright well let's see okay here we're on let's try and click and there you go everything still works but now I can click multiple times in the game no longer tanks since the underlying mesh is only a being updated at most once per frame awesome so here it is our final heat map visualization and the underlying grid system this can be used for just about anything you want you can use it for example like in barrel round tycoon for making an environment map so as I place environment objects the environment becomes better which gets enjoy environment objects all have a certain value and a certain radius and when put together they combine into better values you could also use it as a secondary pathfinding map to tell units which areas should be avoided and which should be desirable the pathfinding would avoid red areas and move towards green errors so by now I think you can see how weird maps and heat maps are extremely versatile and can be used in a multitude of situations so think about how you can apply it to your game as always you can download the project files and utilities from unity cosmic comm if you liked the video subscribe channel for more ent tutorials post any questions you have in the comments and I'll do my best to answer them alright see you next time [Music] you
Info
Channel: Code Monkey
Views: 33,077
Rating: undefined out of 5
Keywords: unity heatmap, unity heatmap tutorial, unity heat map, unity heatmap analytics, unity grid system, unity grid map, unity grid, unity grid layout, 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, programming, tutorial, how to, howto, learn unity, game dev, unity gamedev, unity indiedev
Id: mZzZXfySeFQ
Channel Id: undefined
Length: 28min 15sec (1695 seconds)
Published: Sun Oct 06 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.