• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by Heffalus · Mar 20, 2015 at 05:38 PM · c#coroutineyieldwaitforsecondsfootsteps

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.

Comment

People who like this

0 Show 0
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
Best Answer

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.

Comment
immersiveGamer
Heffalus

People who like this

2 Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image immersiveGamer · Mar 20, 2015 at 08:56 PM 0
Share

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);
     }
 }

avatar image Heffalus · Mar 20, 2015 at 09:47 PM 0
Share

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.

avatar image Heffalus · Mar 21, 2015 at 02:41 PM 0
Share

immersiveGamer, ive tried the while loop but it just crashes unity upon starting the game.

avatar image siaran · Mar 21, 2015 at 02:45 PM 0
Share

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 :)

avatar image Heffalus · Mar 21, 2015 at 02:58 PM 0
Share

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

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

22 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

What is wrong with this use of WaitForSeconds? 1 Answer

Coroutine wait is not working 1 Answer

Waypoint / Yield help 1 Answer

C# WaitForSeconds isn't waiting for any seconds 2 Answers

Trouble Resuming after Yielding while Inside Coroutine 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges