- Home /
Audio Play Once
So i have a quest system and i need the audio to only play once, how would i do that ?
using UnityEngine; using System.Collections;
public class QuestSystem : MonoBehaviour {
// Quest things
public bool isitCompleate;
public bool Objectives_triger;
public bool inturuption;
// what quest?
public bool Quest1;
//Sounds
public AudioSource audio_source;
public AudioClip sound;
public bool Mute;
//Quest Audio
public AudioClip audioname;
public AudioClip QuestOneStart;
public AudioClip QuestOneinturuption;
public AudioClip QuestOneEnd;
// Use this for initialization
void Start () {
Mute = false;
GetNewAudio();
sound = (AudioClip)Resources.Load("audioname");
Quest1 = true;
}
// Update is called once per frame
void Update () {
audio_source.clip = sound;
if (Quest1 == true)
QuestOne();
}
void QuestOne(){
// Confiremed start Audio / Objective
if (isitCompleate == false){
sound = QuestOneStart;
if (Mute == false){
if (!audio.isPlaying)
audio_source.Play();
}
}
if (inturuption == true){
sound = QuestOneinturuption;
if (Mute == false){
if (!audio.isPlaying)
audio_source.Play();
}
}
if (isitCompleate == true){
sound = QuestOneEnd;
if (Mute == false){
if (!audio.isPlaying)
audio_source.Play();
}
}
}
void GetNewAudio(){
audio_source = (AudioSource)gameObject.AddComponent("AudioSource");
// sound = (AudioClip)Resources.Load("audioname");
}
}
Answer by aldonaletto · Jul 14, 2012 at 04:13 PM
This seems to be a problem of logic: you're playing the sounds at Update, which occurs every frame - the first sound, for instance, will be repeated continuously while isitComplete is false. I suppose you're trying to make a state machine: play the first sound, then wait the question be answered or interrupted, then play the appropriate sound and pass to the next question, and so on - am I correct? If so, you could use coroutines: use a switch to select the question, then enter the question coroutine: a coroutine can play the start sound and wait for interruption or isitComplete to become true, then play the appropriate question and increment questNum, a variable that shows which question is selected. You should also add an AudioSource component to your object only once in the Editor, and use it for all sounds - adding an AudioSource for each sound is unnecessary, and wastes memory and time.
EDITED: Yielding to another coroutine in C# apparently doesn't chain it like in JS, thus I changed the code to just start the question coroutine and wait till it finishes.
using UnityEngine; using System.Collections;
public class QuestSystem : MonoBehaviour {
// Quest things public int questNum; // which question public bool isitComplete; public bool Objectives_triger; public bool interruption;
//Sounds public bool Mute;
//Quest Audio - clips for start, interrupt and end public AudioClip sndStart; public AudioClip sndInt; public AudioClip sndEnd;
void GetSounds(string sStart; string sInt; string sEnd){ // load the specified audio clips: sndStart = (AudioClip) Resources.Load(sStart); sndInt = (AudioClip) Resources.Load(sInt); sndEnd = (AudioClip) Resources.Load(s End); }
IEnumerator Start () { Mute = false; questNum = 1; // start with question 1 while (true){ switch (questNum){ case 1: StartCoroutine(Question1()); // start Question1 coroutine while (waiting) yield return 0; // wait until it finishes break, case 2: StartCoroutine(Question2()); // start Question2 coroutine while (waiting) yield return 0; // wait until it finishes break;
// add here other questions as
// new cases like above
default: // invalid question number finishes script
return;
}
}
}
}
bool waiting = false; // this flag shows that a question coroutine is running
// repeat this code for each question: IEnumerator Question1(){ waiting = true; // question coroutine started // get the sounds for this question: GetSounds("QuestOneStart", "QuestOneInterrupt", "QuestOneEnd"); // play the start sound: audio.PlayOneShot(sndStart); // do nothing while interruption and isitComplete are false: while (!interruption and !isitComplete){ yield return null; // let Unity free till next frame } if (interruption){ // if question interrupted play sndInt audio.PlayOneShot(sndInt); // if you want to abort the whole thing... questNum = -1; // set questNum to a non-existent question number } if (isitComplete){ // if question completed... // play sndEnd... audio.PlayOneShot(sndEnd); // and pass to the next question, if any: questNum++; } waiting = false; // question finished }
}
Thank you :) but how do i make the audio play i fixed the little errors in your script like the inability to do yield return new. and now the script is error free but no sound plays
I've just realized that *yield*ing to another coroutine in C# apparently doesn't work as expected: in JS, yielding to another coroutine works like a call to a regular routine - the caller code is resumed only when the routine finishes. I tried this in C#, but the coroutine yielded simply does nothing!
I edited my answer to include a brute force approach while this coroutine chaining mystery is unsolved.
$$anonymous$$ystery solved: in C#, you can't just yield to another coroutine this way:
yield return OtherCoroutine();
this does simply nothing! You must ins$$anonymous$$d use StartCoroutine explicitly:
yield return StartCoroutine(OtherCoroutine());
This isn't correctly informed in the docs (http://docs.unity3d.com/Documentation/ScriptReference/Coroutine.html)
the lines
default: // invalid question number finishes script return;
dont work :(
That's one more C# trap - it should be:
default:
return false;
}
Actually, this only finishes the Start coroutine (which was running in the background), and nothing else happens. You can use the default case to do other more useful things: I would set a boolean variable, and check this variable in Update, doing the appropriate stuff when it becomes set - like this:
bool endQuestions = false;
IEnumerator Start(){ ... default: endQuestions = true; return false; } }
void Update(){ if (endQuestions){ Application.LoadLevel(2); } }
Your answer
Follow this Question
Related Questions
How To Turn Off Sound For Certain Objects? 1 Answer
Audio Scripting 1 Answer
Audio listener to mono then to left or right speaker? 2 Answers