Dynamic Footsteps For Terrains and Imported Meshes Unity3D

Show video

anyone who has worked with standard unity assets  before will immediately recognize these sounds changing the default sounds can instantly improve  our game's appeal but we can do even better than   that g'day everyone in this video we're going  to set up a system to detect what surface the   player is walking on and change the footsteps to  match i'm using the first person controller that   comes with the standard assets as it already has  the logic in place to call random footstep sounds   incrementally in this project i have sound effects  for five different surfaces and for each surface   there are four footstep sounds and a jump and a  landing sound so with our standard assets imported   let's head to where our first person controller  prefab is stored and we'll drag one into the   scene over in the inspector under footstep sounds  we'll click on the little arrow here and expand   that to see that we only have two footstep  sounds in here and they don't sound that great   this is where we're going  to load in our own footsteps   so before we start we'll have to take  our first person controller script   drag it out of the standard assets folder  and put it into our own scripts folder   and this is because all of the scripts  that sit within the standard assets folder   will be compiled before the scripts from  most other folders so we won't be able to   reference any custom classes from a script  that sits inside our standard assets folder   so let's open up our first  person controller script and we'll start by adding using system  dot collections dot generic at the top   here that'll give us access to change this  audio clip array into a list of audio clips right here we'll set this to be a new list  of audio clip and this is because we want to   dynamically add and remove audio clips into this  variable here which can't be done with an array   so because we've changed this to a list  it'll also bring up an arrow down here   where we need to change length to count   save that head back in unity and we'll have  a look at the terrain if we navigate over   to the paint textures tab you can see that  we've got four different terrain layers here   each with a very simple and descriptive name grass  rock mud gravel and these names are what we're   going to be checking for in our code so let's  create a new script we'll call it terrain checker and this script will contain all of the logic  we need to figure out which layer of the terrain   our player is standing on so we  can get rid of start and update   and we also don't need to derive from  monobehaviour the first function we   need will be private and will return an array of  floats we'll call this get texture mix and for the   parameters we'll pass in a vector3 which will be  the player pause and a terrain which we'll call t now we want to store a few of the  components attached to our terrain here   so we want to store its position  we'll type in vector 3 t pos is equal to t dot transform.position   and the terrain data which we'll call t data  and this will be equal to g dot terrain data so we also want to store our players x and  z positions relative to where they are on   the terrain and this line can be a bit  confusing so we'll start with the x-axis   we'll create a new int call it map x  this will be equal to player pause.x   minus t pos dot x so the player position minus  the terrain position we'll wrap this in brackets divide that by t data dot size dot x   and then multiply the whole thing  by t data dot alpha map width now this will come up as an error because we're  trying to put a float value into an integer   so we'll just round this off to  an int math f dot round to int   and there we have it we have our players x  position relative to where they're standing on   the terrain so to get the z position we can just  duplicate this and change all of the x's for z's and we want to change alpha  map width to alpha map height then from these two values we're  going to create a 3d array of floats   and we'll call this splat map data this  will be equal to t data dot get alpha maps so if we look at the description for get  alpha maps it returns a 3d array of floats   where the third dimension represents the mixing  weight of each splat map at each xy coordinate   and while that is an accurate description of what  it does it's not exactly user-friendly i have an   example to show you what that line does so head  back into unity disable my first person controller   and enable the example game object here so i'll  hit play and i can drag around this cross here   and it will tell me all of the different texture  weights at that point if i drag it in the middle   here we've got a combination of all of the  different texture weights over here we can see   that the gravel is the only texture at this point  grass is the only texture at this point rock and   mud and these are the values that will be going  into the third column of our splat map data array   so we'll stop that and head back into visual  studio what we want to pass in here is map x map z   and we want a width and a height of one  now again what this is going to be doing is   populating the third column of our array with all  the different texture weights at these two points   with a width and height of one so let's create a  new array to store all of those values it'll be a   float array we'll call it cell mix i will set this  to be a new float array the size of which will   be splatmap data dot get upper bounds and in here  we'll pass in two and then we'll plus one to that   now we just need to extract all of the values  into cell mix so we want a for loop and this   will go into cell mix dot length and all we want  to do in here is set cell mix at the position of   i to equal splat map data and we don't care about  the first two columns all we care about is the   third one so we'll put an i there now outside  of the for loop we can just return cell mix next up we want to create a new public function  which will return a string and we'll call this   get layer name this will take in the same  parameters as get texture mix vector3 play a pause and a terrain which we'll call t and in here we want to store the result of get  texture mix so float and we'll call this cell mix   and this will be equal to get texture mix and pass  in the player pause and t now we want to create a   float value for the strongest texture we'll call  that strongest we'll set this to zero and we want   to create an int for the index of the strongest  texture so we'll call this max index and this will   also be set to zero now we can loop over all of  our values and find the strongest texture so we'll   loop until cell mix dot length and in here we want  to check if cell mix i is greater than strongest then we want to set the max index to equal  i and the strongest to equal cell mix at the position of i now outside the loop  here we can just return t dot terrain data   dot terrain layers at the position  of max index dot name save that we'll   head back into unity and we'll create a new  script and we'll call this footstep swapper in here we'll want a reference to the  terrain checker so private terrain checker and we'll call this checker and we also want a  reference to the first person controller so at   the top of the script here we want to make sure  that we're using unity standard dot first person   now underneath the terrain checker we'll make  a private first person controller call it fpc   and we also want a private string for  the current layer that we are standing on   in start we'll assign our references so checker is  equal to new terrain checker and fpc is equal to   get component first person controller and this  is the script that we're going to stick on the   first person controller and we'll have all of  the logic inside it to raycast down and check   if we actually need to swap our footstep sounds  so we'll save that create a new c-sharp script   and we'll call this footstep collection and this  class is actually going to be a scriptable object   so we can get rid of start and update and at the  top here we want to type in create asset menu file   name is equal to new footstep collection and menu  name is equal to create new footstep collection so in the class we want to create  a new public list of audio clips   we'll call this footstep sounds we also want a public audio clip for the jump  sound and a public audio clip for the land sound save that we'll head back into unity and in my  assets folder i'm going to create a new folder   called footstep collections if i right click here  and go create you can see that we've got a new   menu option for create new footstep collection  this is an instance of the class that we just   wrote so we'll call it grass we'll lock the  inspector head over to where our grass audio clips   are and we can drag in all of our footstep clips  into the list our jump sound and our landing sound   now let's create three more for  each of the other terrain layers now with all of those collections created we  can head back into our footsteps swapper script   and create an array of footstep collections we'll call this terrain footstep  collections so we can get rid of update   we can create a new public void  function called check layers and with this function we're going to  raycast down from the center of the player   we're going to check to see if  there's a terrain underneath us   check if the layer we're standing  on matches our current layer and if it does then we can swap the footsteps  so first off we'll create a raycast hit and then we can do our raycast so if physics dot  raycast will pass in the transform dot position   and we want to recast down so vector three   dot down then we'll store the hit  information at a distance of three   now we want to check if the terrain exists  so if hit dot transform dot get component terrain is not equal to null then we want to check if the layer we're  standing on matches our current layer   so before that we'll store our terrain we'll call it t is equal to hit dot  transform dot get component terrain and now if our current layer is not equal to   checker dot get layer name  we'll pass in our transform dot position and pass in t so if they  don't match then we have stepped on a new   layer and we can set our current layer to equal  checker dot get layer name transform.position t   alright so now we have the layer name stored in  current layer now we want to do a for each loop   over all of our footstep collections we'll call  this collection in terrain footstep collections and we'll check to see if the current layer is equal to collection.name  and that is the name of the  

actual asset file of our footstep collection and in here we haven't created the  function yet but we're going to tell   the first person controller to swap footsteps  and we're going to pass in the collection so we'll head over to the first person controller  script create a new function called swap footsteps this is going to take a footstep collection and in here we're just going to clear  out the m underscore footsteps list then we're going to loop over everything  in the collection dot footstep sounds and we're going to add it back  into m underscore footsteps outside of the loop we'll set the m underscore  jump sound to equal collection dot jump sound   and m underscore land sound to equal  collection dot sound now we want to   head up to the top of the script and add  in a reference for the footstep swapper we'll call this swapper because this exists on  the same game object we can just set this to   get component footstep swapper and there are three places that we need to check  to see if the footstep sounds need to be changed   so at the start of play footsteps audio we can  type in swapper dot check layers we can copy that we also want to check at the start of play jump  sound and we also want to check at the start of   play landing sound and here's a little tip  in play landing sound if we change this to   play one shot and pass in m underscore  land sound it sounds a lot better   now that was a lot of work so let's save  our scripts and we'll head back into unity   we'll enable our first person controller disable  the main camera and the example game object   and we'll add in our footstep swapper  to the first person controller i'll have to drag the first person controller  up a little bit i just realized i'm not getting   anything over here in the corner because i need  to make the footstep collections public okay so   let's go ahead and lock the inspector and drag  all of our collections onto the list over here   and if we hit play we'll  walk over to the gravel area   we can see that the jump sound has changed to  gravel jump gravel land and we've got all the   footsteps in there we'll head over to the mud  over to the rock and head over to the grass you can see that if we jump off one surface time  and land on another it will update on the landing now this will work for terrains but what if  we're standing on a mesh that we've imported   and has a different surface type to anything on  our terrain so i've got a game object here which   is just a cube with a wooden texture we'll turn  that on we'll drag up our first person controller   and this functionality is actually really easy to  add there are a few different ways we can do it   we could just tag the object as would and  check that against the name of our collection   however that might not work in all situations like  if the collider extends the bounce of the mesh   or if we want to use the tag in another  way so instead i'm going to head back   into the scripts folder create a  new c script call this surface type and we'll drag that onto our wood game object  here we'll open it up in visual studio we'll   get rid of start and update and all we really  want in this is a public footstep collection   and we'll call this footstep collection save  that head back into unity and create a new   collection for the wood footsteps lock the  inspector and drag in all of our audio clips all right now we can just drag  this onto our wood game object head back into our footsteps swapper script  and just after we're checking for the terrain   we can check if the hit.transform dot get  component surface type is not equal to null we want to store our footstep collection is equal to hit dot transform  dot get component surface type dot footstep collection we want to set our current layer  to equal collection dot name   and we want to tell our first person controller  swap footsteps pass in the collection   and that's it that's all we need to  do to create a dynamic footstep system   that is easily scalable and will work  with any type of surface in your game thank you very much for watching i hope you  enjoyed the video if you did please like and   subscribe leave any thoughts and suggestions down  in the comment section below thanks for watching

2021-06-29

Show video