Playing the same sound rapidly from a single audiosource vs multiple audiosources - unity3d

Ok let me try and explain...
I am making a card game where it plays a sound effect when a card is added to a pile, but during the setup cards are rapidly added to different piles and it breaks if I use a single Audiosource
If I play it from a single audiosource it seems not to play them all or if it is it's playing them all at once.
vs
If I do it by having an audiosource on each pile and use that instance of it and hear the different effects played.
I am in the middle of rewriting the game as the first time was a dry run and didn't know what I was going to need and is a bit rough and came across this while trying to streamline the in game audio by having a GameAudioManager singleton to handle the audio.
Is there a reason for this and a solution?
Info
Sound Effect is a MP3 and 3kb
Delay between effects is 0.01f

Choice is yours actually...
Want them to play sequentially ? one audio source is enough and add pending clips to a queue and dequeue them as the currently playing one finishes.
Want them to play individually, separately as the event happens, regardless of whether another card was just added and its effect was still playing, then you use multiple audio sources.
Here's a starting point for a manager that plays audios individually as they're requested.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GameAudioManager : MonoBehaviour
{
// your singleton pattern here, so assuming you now have an instance.
public static GameAudioManager Instance;
// List holds available sources that we can use to play an audio clip.
List<AudioSource> availableSources = new List<AudioSource>();
// Immediately plays a clip, if a cached audio source available, uses it, if none, create new.
public static void AudioPlayOneShot(AudioClip clip, float volume, float pitch, bool loop)
{
Instance.StartCoroutine(Instance.StartPlayingOneShot(clip, volume, pitch, loop);
}
private IEnumerator StartPlayingOneShot(AudioClip clip, float volume, float pitch, bool loop)
{
AudioSource audioSource = GetAudioSource();
audioSource.playOnAwake = false;
audioSource.clip = clip;
audioSource.volume = volume;
audioSource.pitch = pitch;
audioSource.loop = loop;
audioSource.Play();
while (audioSource.isPlaying)
yield return null;
// Whenever this clip stops, add it back to available cache.
CacheAudioSource(audioSource);
}
private void CacheAudioSource(AudioSource audioSource)
{
audioSource.clip = null;
audioSource.playOnAwake = false;
availableSources.Add(audioSource);
}
/// <summary>
/// Gets an audio source from cached list or creates a new one if none available.
/// </summary>
/// <returns></returns>
private AudioSource GetAudioSource()
{
if (availableSources == null || availableSources.Count == 0)
return this.gameObject.AddComponent<AudioSource>();
else
{
AudioSource fromCache = availableSources[0];
availableSources.RemoveAt(0);
return fromCache;
}
}
}
Use like
GameAudioManager.AudioPlayOneShot(yourClip, yourVolume, yourPitch, loop);

The reason it wasn't working was that a AudioSource can only have one instance of itself playing so if it is playing already it is unable to start the new play.
The solution is to either instantiate them as needed or have it on each item and be able to play it from those individual AudioSources.
Hope this helps anyone else coming across this.

Related

Why the sound effect does not work in unity

Why the sound effect does not work in unity?
when I try to add a sound effect, it doesn't work
This is my script to move to the next scene using buttons:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelLoader : MonoBehaviour
{
public Animator transition;
public float transitionTime = 1f;
public void LoadNextLevel()
{
StartCoroutine(LoadLevel(SceneManager.GetActiveScene().buildIndex + 1));
}
public AudioClip impact;
IEnumerator LoadLevel(int LevelIndex)
{
transition.SetTrigger("Start");
yield return new WaitForSeconds(transitionTime);
SceneManager.LoadScene(LevelIndex);
AudioSource.PlayClipAtPoint(impact, transform.position);
}
}
You're making the audio play, and then immediately loading in a different scene. The object that is playing the audioclip also unloads.
You could offset the two by making NewGame() a coroutine instead, with a small timed offset between the PlayClipAtPoint() call and the LoadScene() call.
As Alex Leest said, you are loading new scene right after audio play.
When unity scene loading started, all gameobject except DontDestroyOnLoad Object are destroyed.
So, you may add code below to your Audio Manage class.
(Also, you should ensure that your Audio Manager class always has only one instance in your whole program for not cause bugs)
private void Awake()
{
DontDestroyOnLoad(this);
}

Unity, Volume Slider Problem When Changing Scence

im making a game that have a empty game object for audio source (music) and the script for that music, and i also have a volume slider in diffrent object .
The Script :
float musicVolume = 1f;
private void Update()
{
mainMusic.volume = musicVolume;
}
// Slider will Trigger This
public void SetVolume(float volume)
{
musicVolume = volume;
}
i use that way because it's simple and easy since i will only use 1 music.
With that i can control my music volume correctly, but the problem is when i go to another scence and go back, the slider seems don't do anything so my music volume won't cahange.
So how to i fix it?
Sorry for my bad english. Thanks...
First Of All you can remove Volume initialize From Update Method
Your Problem
When Set Volume From Slider It's Okk set Success Like 0.5f
But After Call Update Methos So Your Volume Set 1f from musicVolume variable
Solution
remove Volume initialize From Update Method
My guess is that the object having the AudioSource is destroied as soon as a new scene is loaded.
Go with this in its script in order to avoid its deallocation when you change the scene:
void Awake () {
DontDestroyOnLoad(this);
}
As a side note, your Update could be avoided because setting the volume at each frame is not optimal.
why not simply
public void SetVolume(float volume)
{
mainMusic.volume = volume;
}
without the Update in between? Do the work only when it is needed!
To your question: it sounds like you are using DontDestroyOnLoad on the mainMusic and loosing the reference due to destroying the duplicate after loading the scene. You should get an exception about that!
However, simply search for the AudioSource in your script like
private void Start()
{
mainMusic = FindObjectOfType<AudioSource>();
}
public void SetVolume(...){ ... }
or if there are multiple AudioSources in your Scene give the main source an explicit type like e.g.
public MainAudioSource : AudioSource
{
// Does nothing but now you can explicitely search for it
}
and then in the other script do
private void Start()
{
mainMusic = FindObjectOfType<MainAudioSource>();
}

How to control audio in another scene on/off in unity

I am making a game now, it's almost done. now I am trying to control the audio on and off by button or toggle button.
The problem is, I put my audio source gameobject in the splashscreen that is in the 1st scene. and I put the audio or music button in the Setting scene which is inside the 3rd scene. I already make the c# script to control the audio but when I've tried to insert the AudioSource, but it can't since it's from a different scene. I've tried to put the AudioSource in the same scene but the audio didn't start except I go to settings scene first.
Here is the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Music : MonoBehaviour
{
static Music instance = null;
public AudioSource Backsound;
private void Awake()
{
if (instance != null)
{
Destroy(gameObject);
}
else
{
instance = this;
GameObject.DontDestroyOnLoad(gameObject);
}
}
public void backsoundOnOff()
{
AudioSource bgsound = Backsound.GetComponent<AudioSource>();
if (bgsound.mute = true){
bgsound.mute = false;
}
else {
bgsound.mute = true;
}
}
}
You have already solved half the problem by using GameObject.DontDestroyOnLoad
The object does indeed exist in both scenes. Now you just need to fetch it.
In the first scene where the created the object, Change the tag of the object. Instead of using one of the exiting tags, create a new tag for it called something such as "MenuMusic". Make sure you assign it after creating it, unity does not assign it automatically
Now, in the 3rd scene, in the game object that needs to access it, create a private field "_music"
in your Start function, add
void Start() {
_music = GameObject.FindGameObjectsWithTag("MenuMusic");
}
You will now have the same instance of Music from scene 1
I would highly recommend referencing the sound script that you have into some sort of game manager. Usually how i work is i have one generic script that controls a multitude of options that i usually call the GameManager. This sets player controls, visual options and sound. From here you can simply set bool whether the player wants the music on and off. If this option wants to change you can reference the GameManager at any point in any script.
//Game Manager code
public void SoundControl(bool soundOff)
{
If(soundOff == true)
{
//Sound Off Control
}else
{
//Sound on Control
}
}
//Reference to game Manager
GameManager manager;
public void TurnOffSound()
{
//Turn sound off through manager
manager =
GameObject.FindGameObjectWithTag("Manager").GetComponent<GameManager>
().SoundControl(true);
}
I find this to be the easiest way to control any options through one script that you can reference anywhere.

Unity2d AudioClip leaves a lasting echo

I have a mono .wav file that I'm trying to play as a PlayOneShot() AudioClip in my game using an AudioSource. The sound plays perfectly in the Unity editor but for some reason echos and leaves a lasting reverb in the game that never goes away. It's called using just a simple PlaySound function from here:
public static void PlaySound (string clip) {
switch (clip) {
case "death":
audioSrc.PlayOneShot (deathSound);
break;
case "move":
audioSrc.PlayOneShot (move);
break;
case "success":
audioSrc.PlayOneShot (success);
break;
}
}
And this AudioSource handles all other sounds perfectly. I don't know what I can even try to change because I'm not messing with any AudioSource options to begin with. Does Unity2d not handle mono sounds well?
I solved my own problem using information found here: https://answers.unity.com/questions/451895/distorted-audio-using-playoneshot.html
The problem was that the PlayOneShot was being called multiple times because the condition to play the noise was met for an extended period of time. To handle this I set a bool to false after it plays one time, and check to see if the bool is true before playing the sound to begin with.
You could do something like this:
public AudioClip[] otherSounds;
AudioSource audioSource;
void Start(){
audioSource = GetComponent<AudioSource>();
}
void Update() {
if(){
audioSource.clip = otherSounds[Index];
}
}

Single Audiosource for multiple clips?

I have a couple of audio sources in a script, idea being that one is used for effects and the other for music. I am noticing that if an effect plays at the same time as another one, it actually stops the previous one from playing, probably because they are playing from the same audio source.
My question is, do I really have to instantiate a new audio source every time i want to play a new sound, just to make sure that one sound will not stop a currently playing one ? Is there a better way ?
The method that plays a sound effect(and the awake one) in my class are these :
void Awake() {
audioSource = GetComponents<AudioSource>()[0];
audioEffectsSource = GetComponents<AudioSource>()[1];
audioSource.volume = PlayerPrefsManager.getMasterVolume();
audioEffectsSource.volume = PlayerPrefsManager.getSFXMasterVolume();
}
public void playSoundEffect(AudioClip clip)
{
if(clip != null)
{
audioEffectsSource.clip = clip;
audioEffectsSource.volume = PlayerPrefsManager.getSFXMasterVolume();
audioEffectsSource.PlayOneShot(clip);
}
}
The script is attached to a musicmanager gameobject with 2 audiosources, one for music fx and one for sound tracks.