Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • 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
0
Question by Rukey4 · Feb 09, 2015 at 12:44 PM · javascriptarraysaudioclip

Never repeat last random audioclip

The code below is merely a snippet of the larger script, I'm curious if there is a way to not repeat the last audioclip. As I'd like the footstep audio to be randomised yet not having you hear the same clip again.

Any help would be greatly appreciated!

 var sounds : AudioClip[]; 
 
 function Update()
 {
     if(grassTimer == 0)
     {
         audio.clip = sounds [Random.Range(0,sounds.length)];
         audio.Play();
     }
 }
Comment
Add comment
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

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by Hoeloe · Feb 09, 2015 at 01:02 PM

I think taxvi has misunderstood your question. You want to select a random sound to play each time, but not use the same one twice, correct?

The problem is, as I'm sure you're aware, that you're selecting from a list of all your sounds, including the one that was just played. What you want to do is select from a list of all sounds except the one that was just played. You could do this by selecting a random sound, checking if it is the one you just played, and if so selecting another, but this is bad practice as it has a small chance of locking up your program.

If you were using C#, I'd tell you to use a library called Linq for this, which allows all sorts of useful array operations, including one that can filter out array elements.

Since you're using Javascript (and I heavily recommend you switch to C# when you can. Javascript may look easier, but it hides a lot of the complexity, which can make problems occur more easily), you can't do this, but you can make your own filter function, somewhat like this:

 function FilterCurrentClip()
 {
      var rtrn : AudioClip[] = new AudioClip[sounds.Length - 1];
      var j : int = 0;
      for(var i : int = 0; i < sounds.Length; i++)
      {
          if(sounds[i] != audio.clip)
          {
               rtrn[j] = sounds[i];
               j ++;
          }
      }
      return rtrn;
 }

This takes the existing array, and creates a new one from the values, skipping the element that you don't want to use.

Now, when you want to set the new clip, you can do this:

  var filteredSounds = FilterCurrentClip();
  audio.clip = filteredSounds[Random.Range(0,filteredSounds.Length)];

This is quite a slow operation, and C#'s Linq would be a lot faster, but it should work (as long as your sounds array always contains the value of audio.clip, otherwise it will break).

Comment
Add comment · Show 6 · 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 Rukey4 · Feb 09, 2015 at 01:22 PM 0
Share

Thanks for the suggestion, I'm trying my best to get my head around this.

I get this error:

IndexOutOfRangeException: Array index is out of range.

Problem on line:

rtrn[j] = sounds[i]

and

var filteredSounds = FilterCurrentClip();

avatar image Hoeloe · Feb 09, 2015 at 01:35 PM 0
Share

That's the error you'll get if the sound clip isn't contained in the sounds array. If your clip is initially empty, this will also happen. You can do a precursor check to see if the sounds array contains the current clip value, and just return the complete array if it doesn't.

avatar image Rukey4 · Feb 09, 2015 at 01:59 PM 0
Share

I understand it's not best to spoon feed people but how do I make a check?

Isn't this our check? if(sounds[i] != audio.clip)

$$anonymous$$y sounds array does contain two clips at runtime. Sorry if these are stupid questions.

avatar image Hoeloe · Feb 09, 2015 at 02:15 PM 0
Share

That's our check to see if the current element in sounds is not equal to the current clip. The problem is that arrays are fixed length, and I'm making the assumption that the new array will always filter exactly one element from the sounds array. If, however, the current clip (that's the one attached to the AudioSource) is not a clip from the sounds array, then the check you've highlighted sounds[i] != audio.clip will always be true, so we'll be trying to copy over every element from the sounds array into another array that is too small to hold them. So, ins$$anonymous$$d, we need to make sure that the array will always be big enough.

Notice how, to rebuild the array, I'm having to loop over all the elements and copy them in? Well, you'll have to do that to make the check. However, that requires you to loop over the array twice, which is generally not a good idea. You can, however, be a little clever, and merge the two loops together with a different check.

Ins$$anonymous$$d of looping through, and checking each element in the array against your current one (which is what I was originally suggesting), you could ins$$anonymous$$d check in the main loop to see if there are too many audio clips to store in the array, and if there are, just return the main array. This requires just a simple test to see if j (the index into the new array) is greater than or equal to the length of the array (arrays are 0-indexed, so the last element in the array is at array index length-1).

 function FilterCurrentClip()
 {
     var rtrn : AudioClip[] = new AudioClip[sounds.Length - 1];
     var j : int = 0;
     for(var i : int = 0; i < sounds.Length; i++)
     {
         if(j >= rtrn.Length)
         {
             return sounds;
         }
         if(sounds[i] != audio.clip)
         {
             rtrn[j] = sounds[i];
             j ++;
         }
     }
     return rtrn;
 }

I suggest you read up about for loops and arrays. There's a nice answer here that explains them in detail: http://answers.unity3d.com/questions/548266/searching-through-an-array.html

avatar image Rukey4 · Feb 09, 2015 at 02:46 PM 0
Share

It works well, not perfect but I'm happy with this. It plays the sounds and on the odd occasion it will play the last played audioclip. It's far better than it was, for my purposes this is great. Thanks for your time.

Show more comments
avatar image
0

Answer by Mmmpies · Feb 09, 2015 at 01:06 PM

Contributed to a similar question over the weekend.

No-repeat

Several methods.

Comment
Add comment · 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

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.

Follow this Question

Answers Answers and Comments

20 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

Related Questions

Having Multiple Controllable FPS Units Selected From A Singular RTS Mode? 0 Answers

Adding sound javascript in unity2d 1 Answer

Javascript 2D arrays: null values and slicing 1 Answer

Converting JS Array to Generic List 2 Answers

2D array error object does not support slicing 0 Answers


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