Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 /
  • Help Room /
This question was closed Nov 19, 2015 at 11:53 AM by Olliepm for the following reason:

The question is answered, right answer was accepted

avatar image
0
Question by Olliepm · Nov 14, 2015 at 02:50 PM · c#scripting problemaudio

How to stop a sound playing once another starts? (C#)

I have a prefab for an object (let's call it chord object) that plays a looping musical chord sound as the player passes through it (on collision). When the player collides with another of these objects, a new chord is played. What I'd like to know how to do is check if a chord loop is already playing and if so, stop that sound playing so that only one chord object (the most recent chord object the player has collided with) plays a sound at a time. I'm using C# and my script attached to the chord object looks like this (it updates the attached audio source component). Currently chords will play back on top of each other in a hideous cacophony, because there's nothing telling them to turn off:

void OnTriggerEnter(Collider other) { //Debug.Log (x);

     if (other.gameObject.tag == "collisionTank") {//If tank collides with this

         Debug.Log ("Play chord");
         chordSource.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

1 Reply

  • Sort: 
avatar image
3
Best Answer

Answer by Le-Pampelmuse · Nov 14, 2015 at 09:08 PM

I suggest having an AudioSource reference stored somewhere called currentAudio that is accessible from each of the audioSources' scripts.

Like an emtpy GameObject that has a script attached where a public AudioSource currentAudio exists.

Then you add a reference to that script into the prefab's script and write something like:

 public AudioManager otherScript;

 void OnTriggerEnter(Collider other)
 {
     if(other.transform.tag == "collisionTank")
     {
         if(otherScript.currentAudio != null) // If we already have a chord playing..
         {
             otherScript.currentAudio.Stop();  // stop the currently playing Chord and..
             chordSource.Play(); // start the new one, that THIS object has attached..
             otherScript.currentAudio = chordSource; // tell the logic that THIS is playing!
         }
         else
         {    //If this is the FIRST collider we entered..
             chordSource.Play(); // ..start the chord, that THIS object has attached..
             otherScript.currentAudio = chordSource; // ..assign the audiosource for later!
         }
     }
 }


And in the AudioManager script you would have:

 public class AudioManager : MonoBehaviour{
     public AudioSource currentAudio;

     void Start()
     {}
 }

I hope this is what you were looking for, it just stops the current audio and immediately starts the next one. You could also fade out quickly, altough this might also sound horrible for a split second since they are chords.

PS: Since you are using Prefabs, I would recommend calling the AudioManager's GameObject "AudioLogic" or something thats easy to identify and at the start of the prefab add:

 public AudioManager otherScript; //this doesnt need to be assigned by you anymore
 void Start()
 {
     otherScript = GameObject.Find("AudioLogic").getComponent<AudioManager>();
 }

This automatically finds the AudioLogic GameObject and gets the AudioManager script from it, so you don't have to assign it for 100 Prefabs by hand. Also when using Prefabs, it would not work to save references they have in the inspector.

Comment
Add comment · 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 Olliepm · Nov 15, 2015 at 03:05 PM 0
Share

Hey, thanks! I'm yet to try this out but reading through it, it does seem like an appropriate solution in theory. There are a few concepts that are new to me so I'll need to actually try implementing this before I can fully get my head round it.

Firstly, is "if(otherScript.currentAudio != null)" another way of saying if(is not playing)? What makes something == null? I get null reference errors a lot, even when things are working properly, so it'd be good to know more about this.

Secondly, am I able to use GameObject.Find() in any script for any object in my project to save me the trouble of dragging and dropping object references into scripts where I've created an unspecified public GameObject?

Hopefully I've understood these thingS correctly.

avatar image Le-Pampelmuse Olliepm · Nov 15, 2015 at 08:54 PM 2
Share

Checking if something is or is not "null" means the following code should only start to execute when the object ( here the AudioSource "currentAudio") is assigned to "something" if you don't add this check and you try to execute line 9 in my example:

otherScript.currentAudio.Stop(); this would give you a "nullreference error" because it "refers" to an object that is not assigned at the time the line is called, it is "null", it doesn't exist for the script.

Generally speaking, being null is the same as if you didn't drag an object into a Inspector slot. The Value is there, but "nothing" is assigned to it.

Here a simple walkthrough what happens in the script:

  1. Scene starts

  2. We have triggers in the scene but the player has not yet touched any of them, so there can be no currentAudio that is playing

  3. As soon as we touch any trigger, we only make it play the audio, we don't need to stop any other audio because currentAudio tells us that there "is no" AudioSource, it is null at the $$anonymous$$oment.
    We additionally assign the new, the first audio to that currentAudio value. Now currentAudio holds a reference to the new audio that is playing, it is now not "null" anymore. You can watch this happen in the Inspector. It means we can access the audio later on, when we touch the next trigger.

  4. Now we touch the next trigger, and because we have a currentAudio, because it isn't null, we need to .Stop() that from playing before we make the new one .Play().
    In the same scope where we said we play the new audio, we need to also change the currentAudio to match that new audio, so we can .Stop() it the next time we touch a new trigger. This code will work without any other further action for as long as the scene is running and for every trigger you might have that has the right tag.

=> http://docs.unity3d.com/ScriptReference/GameObject.Find.html Yes, you definitely are able to do that, and you definitely should NOT do that :) GameObject.Find is a very demanding process, you should only use it where you can't assign object in the Inspector before the game starts. For example when you Instantiate a prefab, you can't assign them by hand because the game is already running.

That's what I was talking about in my comment. When adding a Prefab into the scene, it does not save the references the original object had. So the Audio$$anonymous$$anager would always be a Null Reference Exception when you don't use GameObject.Find in the ChordObject.

I'm not going to explain Nullreference Exceptions since there is enough Documentation about that and this forum is only for questions that can't be answered by tutorials or documentation. You might want to read the FAQ about that, so you can find a solution easier the next time you have a problem. http://docs.unity3d.com/$$anonymous$$anual/NullReferenceException.html http://answers.unity3d.com/page/faq.html

Hope this could help you.

avatar image Olliepm Le-Pampelmuse · Nov 18, 2015 at 02:37 PM 1
Share

Hey - thanks a lot. This is probably one of the most helpful forum replies I've ever had. I eventually got the scripts working, although there are a couple of things about how it works that are still making my head spin. I'll get it eventually =]

If you're still there, you mentioned being able to do fade outs on sounds ins$$anonymous$$d of just stopping them? I'm getting pops and clicks just now so that may not be such a bad idea. There will be other musical layers (notes, arpeggios, ambient sounds etc) that should mask the fades anyway.

Show more comments
avatar image Le-Pampelmuse Olliepm · Nov 18, 2015 at 04:15 PM 2
Share

No problem, I treat people and their questions the same way I want them to treat me. ;)

Yes there are some ways to fade audio volumes, but since that is a very common asked question I suggest you search the forum because:

  • Your question has been answered (please accept the answer, so it is obvious to people that this question is answered before they click on it).
    Additionally you may close the question, this makes it easier for moderators because they don't have to do it then ;)

  • How to fade audio would be another question, but please don't ask "how to fade audio" in a new question ;)

This is a classic example:
Original question: How to stop audio when other audio starts.
New question as a result: How to fade audio out.

You should google "unity how to fade out audio" for that. I give you a hint, you don't need yield or anything fancy:

  • Define a condition when to fade out ( most likely a bool)

  • Decrease the volume over time using Time.deltaTime

  • When it is 0 stop decreasing it, because it can't be decreased anymore.

For example:

 using UnityEngine;
 using System.Collections;
 
 public class FadeAudio : $$anonymous$$onoBehaviour {
     public AudioSource audio;
     public bool FadeNow;
     public float Time$$anonymous$$ultiplier = 5f; //How fast we should fade out.
     void Update()
     {
         if(FadeNow)
         {
             if(audio.volume > 0)
             {
                 //The slower we want to fade, the smaller Time$$anonymous$$ultiplier would be.
                 audio.volume -= Time.deltaTime * Time$$anonymous$$ultiplier;
             }
             else
             {
                 /*If it is down to 0, we don't have to let the script decrement it anymore.
                 Otherwise it would still try to decrement it, which is useless*/
                 audio.volume = 0f;
             }
         }
         else
         {
             audio.volume = audio.volume; // $$anonymous$$ake sure it doesnt change, just in case.
         }
     }
     
 }

If you still have any questions, you will find the answers via Google ;) Hope I could help again.

Follow this Question

Answers Answers and Comments

37 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 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

OnTriggerEnter Footsteps Multiple Times A Second 1 Answer

There is a problem with my script... 0 Answers

I need help with code for audio file. 0 Answers

Soundarray for player is not working properly 1 Answer

Trouble changing sound when going through a collider. 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