- Home /
Playing footsteps with interval
 using UnityEngine;
 using System.Collections;
 
 public class AdvancedFootsteps : MonoBehaviour
 {
 
         // character controller reference
         CharacterController characterController;
 
         // script referencec
         tpAnimator tpanimator;
 
         // audio source
         AudioSource audio;
 
         //Audio clips
         public AudioClip woodStep;
         public AudioClip waterStep;
         public AudioClip metalStep;
         public AudioClip grassStep;
         public AudioClip dirtStep;
         public AudioClip stoneStep;
         public AudioClip sandStep;
     
         // intervals between steps
         float runningInterval = 0.2f;
         float walkingInterval = 0.5f;
         float crouchingInterval = 1f;
 
         /** step volumes
         float runningVolume;
         float walkingVolume;
         float crouchingVolume; **/
 
         bool playsteps;
 
         void Awake ()
         {
                 characterController = GetComponent<tpController> ().characterController;
                 tpanimator = GetComponent<tpAnimator> ();
                 audio = GetComponent<AudioSource> ();
         }
 
 
 
         void Start ()
         {
                 playsteps = true;
                 StartCoroutine ("PlayFootsteps");
         }
 
 
         void Update ()
         {
                 Debug.Log ("Update");
                 if (characterController.isGrounded && !playsteps && characterController.velocity.magnitude > 0.2f) {
                         playsteps = true;
                         StartCoroutine ("PlayFootsteps");
                 }
 
                 if (!characterController.isGrounded && playsteps) {
                         playsteps = false;
                         StopCoroutine ("PlayFootsteps");
                 }
         }
 
         IEnumerator PlayFootsteps ()
         {
                 float vel = characterController.velocity.magnitude;
                 RaycastHit hit;
                 string floorTag; 
                 if (characterController.isGrounded && vel > 0.2f) {
                         if (Physics.Raycast (transform.position, Vector3.down, out hit)) {
                                 floorTag = hit.collider.gameObject.tag;
 
                                 if (floorTag == "Wood") {
                                         audio.clip = woodStep;
                                 } else if (floorTag == "Water") {
                                         audio.clip = waterStep;
                                 } else if (floorTag == "Metal") {
                                         audio.clip = metalStep;
                                 } else if (floorTag == "Terrain") {
                                         // check texture and get correct clip
                                         int t = GetMainTexture (transform.position);
                         
                                         switch (t) {
                     
                                         case 0:
                                                 // grass
                                                 audio.clip = grassStep;
                                                 break;
                         
                                         case 1:
                                                 // dirt
                                                 audio.clip = dirtStep;
                                                 break;
                         
                                         case 2:
                                                 // stone
                                                 audio.clip = stoneStep;
                                                 break;
                         
                                         case 3:
                                                 // gravel
                                                 audio.clip = stoneStep;
                                                 break;
                         
                                         case 4:
                                                 // sand
                                                 audio.clip = dirtStep;
                                                 break;
                         
                                         case 5:
                                                 // wet mud
                                                 audio.clip = dirtStep;
                                                 break;
                         
                                         case 6:
                                                 // branches
                                                 audio.clip = stoneStep;
                                                 break;
 
                     
                                     case 7:
                                             // snow
                                             audio.clip = stoneStep;
                                             break;
                     
                                     case 8:
                                             // concrete
                                             audio.clip = dirtStep;
                                             break;
                                     }
                             }
                             // Play the correct sound
                             audio.PlayOneShot (audio.clip);
                             if (tpanimator.isRunning) {
                                     yield return new WaitForSeconds (runningInterval);        
                             } else if (tpanimator.isCrouching) {
                                     yield return new WaitForSeconds (crouchingInterval);        
                             } else {
                                     yield return new WaitForSeconds (walkingInterval);        
                             }
                             playsteps = false;
                     } else {
                             yield return null;
                     } 
             }
             
     }
}
Edit: working script, i will not take credit for most of the code since it is a combination of scripts found on this site.
Answer by siaran · Mar 20, 2015 at 08:27 PM
that's a lot of else-if statements you have there, consider at least turning those into a switch.
anyway, onto your problem
You are calling audio.PlayOneShot inside update, so it will play every frame. Yes, you're calling it after StartCoroutine, but thats not how that works. Also starting a coroutine in every update frame is generally not a great idea...instead you will want do something like
 void Start(){
  StartCoroutine(Footsteps());
 }
 
 IENumerator Footsteps(){
  audio.PlayOneShot(clip);
  yield return new WaitForSeconds(interval);
  StartCoroutine(Footsteps());
 }
Of course this gives you the problem that you cannot stop your Footsteps sounds, but thankfully there is http://docs.unity3d.com/ScriptReference/MonoBehaviour.StopCoroutine.html
so you will get something like
 IENumerator coroutine;
 bool playsteps;
 
 void Start(){
  playsteps = true;
  coroutine = Footsteps();
  StartCoroutine(coroutine);
 }
 
 void Update(){
  //controller is grounded and moving but we are not playing footsteps
  if(characterController.isGrounded && !playsteps && velocity > 0.2f){
    playsteps = true;
    StartCoroutine(coroutine);
    
   }
  //controller is not grounded but we are playing steps - stop playing
  if(!characterController.isGrounded && playsteps){
   playsteps = false;
   StopCoroutine(coroutine);
  }
   /*
    You;ll want some additional start-stop conditions, like if velocity is 
    low also stop playing or something.
   */
 }
Well, something like that. I've never actually used StopCoroutine so I have no idea if this actualy works. Long story short your problem is that you are starting your audio play and coroutine every frame.
I have used StopCoroutine like that before. I find it useful for loops that you want to stop. I would have done a while loop for the coroutine though
 IENumerator Footsteps(){
     while(true)
     {
          audio.PlayOneShot(clip);
          yield return new WaitForSeconds(interval);
     }
 }
Thanks for your answer, are there any advantages on using a switch? Amountwise the code wont be any shorter, more readable tho.
Will try the rest of the answer tomorrow and get back to you.
immersiveGamer, ive tried the while loop but it just crashes unity upon starting the game.
more readable code is an advantage in itself.
switches are also faster than if-else ladders because the compiler is better at optimizing them, although that is probably not a difference you will notice. In which case you should use the more readable option, which in this case is also a switch :)
ah okay, your suggestion worked, added a playstep = false; at the end of the coroutine. Will upload the edited script now if anyone has any use for it :)
Your answer
 
 
              koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                