Play audio once while condition is met in update function (C#)
Ok so, first off, I'm quite new to programming so my code is probably quite messy and inefficient so what I'm doing is, I have a clock type thing with two hands and 4 inner sections and 3 outer sections. the inner hand completes a full revolution in the time that the outer hand completes one section.
here's my code
using UnityEngine;
using System.Collections;
public class clockHandScript : MonoBehaviour {
private float handSpeed;
public float hand2per1 = 3;
public AudioClip[] audioArray = new AudioClip[7];
private AudioSource audio1;
float audioLengths;
GameObject hand2; //small hand
int aud1; //the audio that plays based on big hand
int aud2; //the audio that plays based on small hand
void Start () {
audio1 = GetComponent<AudioSource> ();
hand2 = GameObject.Find("Hand 2");
}
IEnumerator playSound(){
audio1.clip = audioArray [aud1];
audio1.Play (); //plays big hand audio
yield return new WaitForSeconds (audio1.clip.length);
audio1.clip = audioArray [aud2];
audio1.Play (); //plays small hand audio after big hand audio
}
void Update () {
audioLengths = audioArray [aud1].length + audioArray [aud2].length;
//clock hands spinning
transform.RotateAround (Vector3.up, Vector3.up, (1 / audioLengths) * 30 * Time.deltaTime);
hand2.transform.RotateAround (Vector3.up, Vector3.up, (1 / audioLengths) * 90 * Time.deltaTime);
//if hand is between these two angles audio will play
if (hand2.transform.eulerAngles.y >= 315 || hand2.transform.eulerAngles.y <= 44.9f) {
aud2 = 3;
StartCoroutine(playSound());
//**How do I make this^^ only play once?**
}
if (hand2.transform.eulerAngles.y >= 45.1f && hand2.transform.eulerAngles.y <= 134.9f) {
aud2 = 4;
StartCoroutine(playSound());
}
if (hand2.transform.eulerAngles.y >= 135.1f && hand2.transform.eulerAngles.y <= 224.9f) {
aud2 = 5;
StartCoroutine(playSound());
}
if (hand2.transform.eulerAngles.y >= 225.1f && hand2.transform.eulerAngles.y <= 314.9f) {
aud2 = 6;
StartCoroutine(playSound());
}
if (transform.eulerAngles.y >= 300.1f || transform.eulerAngles.y <= 59.9f) {
aud1 = 0;
}
if (transform.eulerAngles.y >= 60.1f && transform.eulerAngles.y <= 179.9f) {
aud1 = 1;
}
if (transform.eulerAngles.y >= 180.1f && transform.eulerAngles.y <= 299.9f) {
aud1 = 2;
}
}
}
How can I make it so that when the hand is between the two angles the audio is triggered to play once??
once again, this is probably extremely messy and inefficient so excuse me and give me some pointers please.
Answer by losingisfun · Jan 03, 2017 at 02:22 PM
I think you're looking for 'PlayOneShot' - try:
audio1.PlayOneShot (clip);
as for the IEnumerator, try putting a delay on it like:
private bool busy = false;
//when you start the Coroutine add an if statement:
if (!busy) {
busy = true;
StartCoroutine(playSound());
}
IEnumerator playSound() {
AudioClip clip = audioArray [aud1];
audio1.PlayOneShot (clip);
yield return new WaitForSeconds (clip.length);
AudioClip clip = audioArray [aud2];
audio1.PlayOneShot (clip);
//give it as long as it needs for the angle to change
yield return new WaitForSeconds (1.0f);
busy = false;
}
it's a fairly poor example, but i'm sure it will work
Answer by UnityCoach · Jan 03, 2017 at 02:24 PM
Update () is called every frame, and will Start your Coroutine every frame unless a condition prevents it. So you need another condition than just the position/angle.
For example, you can declare a private bool _isPlaying
, then query it value to start the coroutine, like
if (!_isPlaying)
StartCoroutine (playSound());
and in the coroutine, you immediately set this to true, until you set it back to false
IEnumerator playSound()
{
_isPlaying = true;
audio1.clip = audioArray [aud1];
audio1.Play (); //plays big hand audio
yield return new WaitForSeconds (audio1.clip.length);
audio1.clip = audioArray [aud2];
audio1.Play (); //plays small hand audio after big hand audio
yield return new WaitForSeconds (audio1.clip.length);
_isPlaying = false;
}
This isn't the best option, as depending on the speed of your meter, and the length of audio files, you may still have it play more than once, but it should put you in the right direction.
Your answer
Follow this Question
Related Questions
Why does this condition keep being true even if its not? 0 Answers
AudioSource in Update 1 Answer
Keeping Score out of Update Function 1 Answer
Listening to Sound Card Output 0 Answers
Help destroying a seperate game object on collision enter 1 Answer