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.

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

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.