Unity2d AudioClip leaves a lasting echo - unity3d

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];
}
}

Related

Unity Particles Aren't working with custom script

I started my game dev journey a few weeks ago and I am enjoying it, but sometimes it can get frustrating when things do not work.
I wrote a very basic code for particle system, if we press space then particle should play. The problem is that its not playing, when I hit play it doesn't work for some reason. When I click the particle in the scene then it works and it also works when I check on the play on awake
The Code:
[SerializeField] ParticleSystem engineBoostParticle;
[SerializeField] ParticleSystem sideEngineParticles;
void Start()
{
}
void Update()
{
ThrustingInput();
}
void ThrustingInput()
{
if (Input.GetKey(KeyCode.Space))
{
if (!engineBoostParticle.isPlaying)
{
engineBoostParticle.Play();
}
}
else
{
AS.Stop();
engineBoostParticle.Stop();
}
}
You want to check engineBoostParticle.isEmitting as well as isPlaying in your if statement.
It's possible that your system is playing, but not emitting (because the loop is over), so make sure the particle system loops properly as well.

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

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.

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.

Why is it SO Hard to Just Mute a Sound in Unity?

I have spent all day looking for a solution to this problem, and I simply can't find one. Using JavaScript in Unity 3D, I have a script where I want to play a sound when the player's velocity on the X axis reaches a certain point, and if it's not at that point, then the sound will be muted. And I believe I have all the structure right, it's just the line of code that says to mute the audio that won't work. I've tried all kinds of different combinations, and I get an error for each one.
The script looks like this:
#pragma strict
var playing = false;
var audioSource = GetComponent.<AudioSource>();
function Update () {
if (transform.GetComponent.<Rigidbody>().velocity.x <= 2.5 &&
transform.GetComponent.<Rigidbody>().velocity.x >= -2.5)
{
Mute();
} else {
Unmute();
}
}
function Mute () {
audioSource.mute = true;
}
function Unmute () {
audioSource.mute = false;
Sound();
}
function Sound () {
if (transform.GetComponent.<Rigidbody>().velocity.x >= 2.5 && playing ==
false)
{
playing = true;
GetComponent.<AudioSource>().Play();
yield WaitForSeconds(2);
playing = false;
}
if (transform.GetComponent.<Rigidbody>().velocity.x <= -2.5 &&
playing == false)
{
playing = true;
GetComponent.<AudioSource>().Play();
yield WaitForSeconds(2);
playing = false;
}
}
I've gotten all kinds of different errors, but the one I seem to be getting the most says "UnityException: GetComponentFastPath is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead. Called from MonoBehaviour 'motioncheck' on game object 'Ball'." I'm not sure what this means, since I'm still kinda a nub at JavaScript.
I feel like it shouldn't be this hard to just mute a sound. I'm going to assume that the answer to this is really simple and that I'm just really dumb. That's what usually seems to happen, lol.
In the mean time, I'm going to continue my rampage across the internet in search for answers to this problem.
Your mute code is fine.
"UnityException: GetComponentFastPath is not allowed to be called from
a MonoBehaviour constructor (or instance field initializer), call it
in Awake or Start instead. Called from MonoBehaviour 'motioncheck' on
game object 'Ball'." I'm not sure what this means, since I'm still
kinda a nub at JavaScript.
See this:
var audioSource = GetComponent.<AudioSource>();
That's a Unity API and you have to call their functions from inside a function. The Awake or Start function is appropriate for initializing component variables.
var audioSource : AudioSource;
function Start()
{
audioSource = GetComponent.<AudioSource>();
}
Note that Unityscript/Javascript is now discontinued. They no longer update the doc on this and you cannot create new scripts from the Editor anymore. It still works as for now but the compiler will be removed soon. Please learn and start using C# before its support is totally removed.

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.