Unity AudioSource unable to play clip - c#

I am attempting to play a sound when a user drags a 2D gameobject.
The gameobject will have to play many sounds, so I am programmatically creating Audio Sources and assigning clips through the inspector.
public class Card: Monobehavior, IDraggable {
public AudioClip tokenGrabClip;
public AudioClip tokenReleaseClip;
public AudioSource tokenGrab;
public AudioSource tokenRelease;
public AudioSource TokenGrab {
get{ return tokenGrab; }
}
public virtual void Start() {
tokenGrab = AddAudio (tokenGrabClip, false, false, 1f);
tokenRelease = AddAudio (tokenReleaseClip, false, false, 1f);
}
public virtual AudioSource AddAudio(AudioClip clip, bool isLoop, bool isPlayAwake, float vol) {
AudioSource newAudio = gameObject.AddComponent<AudioSource>();
newAudio.clip = clip;
newAudio.loop = isLoop;
newAudio.playOnAwake = isPlayAwake;
newAudio.volume = vol;
return newAudio;
}
}
This will create two audio sources for every gameobject of type Card in my game.
Now in my game manager, I simply try to play a sound...
void CheckDragStart(GameObject go, Draggable d) {
if (go.GetComponent<Card> () != null) {
print("check drag start");
go.GetComponent<Card> ().TokenGrab.Play ();
}
}
No sound is played, but I am able to to see my console with the "check drag start message".
Any idea what I could be doing wrong? I can see audio sources assigned to my game objects with my methods in the first code block, but my audio clips are not being assigned to them...

This can't be that go GameObject, GetComponent<Card>() or TokenGrab is null. If any of them is null, you will get the NullException error. I am ruling those out.
Looking at your code, these are the possible reasons why your audio is not playing. Ordered from very likely to least.
1.Your AudioClip is not assigned from the Editor.
Check that both of these variables are assigned fom the Editor.
public AudioClip tokenGrabClip;
public AudioClip tokenReleaseClip;
This must be done for each Card script that is attached to any GameObject in the scene.
You won't get any error if they are not assigned or null. It simply won't play.
2.Your Card script and the GameObject it is attached to is destroyed after Play() is called. Try to comment anywhere you have the Destroy function. Try it again. If problem is solved you have to fix that by moving your AudioSource to an empty GameObject that does not need to be destroyed.

I am just putting up my suggestion here. I see that you don't want to loop the clips. So why don't you try something like this?
public AudioClip tokenGrabClip;
public AudioClip tokenReleaseClip;
AudioSource audioSrc;
void Start () {
audioSrc = GetComponent<AudioSource> ();
}
public void PlayTokenGrabClip () {
audioSrc.PlayOneShot (tokenGrabClip);
}
public void PlayTokenReleaseClip () {
audioSrc.PlayOneShot (tokenReleaseClip);
}
Add an AudioSource component to your GameObject. Assign the audio files (mp3, wav) to tokenGranClip and tokenReleaseClip through the editor. Then call the functions PlayTokenGrabClip () and PlayTokenReleaseClip () to play the respective sounds as and when required.

The problem came from not updating my prefabs. I was assigning AudioClips in my C# script publicly, however, this change was not immediately reflected in my prefabs. Rather than having to update many prefabs, I reorganized how my resources load on startup:
I define my audio clips with Resources.Load(...) as AudioClip; in Awake() and create AudioSource Components in Start(). From this, I am able to add AudioClips to my AudioSources via C#.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Card : MonoBehaviour, IDraggable {
public bool counter;
private AudioClip tokenGrabClip;
private AudioClip tokenReleaseClip;
private AudioSource tokenGrab;
private AudioSource tokenRelease;
public AudioSource TokenGrab {
get{ return tokenGrab; }
}
public AudioSource TokenRelease {
get{ return tokenRelease; }
}
public virtual void Start() {
tokenGrab = AddAudio (tokenGrabClip, false, false, 0.5f);
tokenRelease = AddAudio (tokenReleaseClip, false, false, 0.5f);
}
public virtual void Awake () {
tokenGrabClip = Resources.Load ("Audio/tokenGrab") as AudioClip;
tokenReleaseClip = Resources.Load ("Audio/tokenRelease") as AudioClip;
}
public virtual AudioSource AddAudio(AudioClip clip, bool isLoop, bool isPlayAwake, float vol) {
AudioSource newAudio = gameObject.AddComponent<AudioSource> () as AudioSource;
newAudio.clip = clip;
newAudio.loop = isLoop;
newAudio.playOnAwake = isPlayAwake;
newAudio.volume = vol;
return newAudio;
}
}

Related

Unity 2d Random Music start only on first time

im programming an simple Unity 2d Game and I want to add some Background music, I have an script that random starts an Title from an playlist, but when im rejoining the MainMenu Scene where the Music GameObject is located, another Song starts playing (2 Songs Playing), but I want that only one song is playing, the song that was first. I saw when I rejoined the MainMenu scene that another music object where created.
here my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MusicRandom : MonoBehaviour
{
[SerializeField] AudioClip[] myAudioClips;
AudioSource audioSource;
void Start()
{
DontDestroyOnLoad(gameObject);
audioSource = gameObject.GetComponent<AudioSource> ();
}
AudioClip RandomClip()
{
int randomNumber = Random.Range(0,myAudioClips.Length);
AudioClip randomClip = myAudioClips[randomNumber];
return randomClip;
}
void Update()
{
if (!audioSource.isPlaying) {
audioSource.clip = RandomClip();
audioSource.Play();
}
}
}
I tried to add an value that start the "audioSource = gameObject.GetComponent ();" function only one time, but it doesn't worked.
I found an way that the GameObject not duplicate
private static GameObject instance;
void Start()
{
DontDestroyOnLoad(gameObject);
if (instance == null)
instance = gameObject;
else
Destroy(gameObject);
}

Unity C# - I want to play multiple audio sources on the same game object in unity

I have a flappy bird type game and I want the character to make one sound when successfully passing through the pipes and a different sound when it hits the pipes or ground. So I have this code set but I cant figure out how to call to the separate audio sources. Seems to always just want to play the first audio source in my inspector. I have this script set on the game character.
'''
public AudioSource bing;
public AudioSource crash;
void Start()
{
bing = GetComponent<AudioSource>();
crash = GetComponent<AudioSource>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("column"))
{
bing.Play();
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("ground") ||
collision.gameObject.CompareTag("pipe"))
{
crash.Play();
}
}
First, you can't get two or more components of the same type from the same GameObject with the GetComponent() function, you either need to use the GetComponents() function or put the components on different GameObjects.
However, in your case, you should only use one AudioSource since the audio should come from the same place (the bird). You should instead add two AudioClips and play those with the same AudioSource by using the PlayOneShot() function.
Something like this:
private AudioSource ourAudioSource;
// The attribute will make the private field visible in the editor.
[SerializeField]
private AudioClip bing;
[SerializeField]
private AudioClip crash;
void Start()
{
ourAudioSource = GetComponent<AudioSource>();
Assert.IsNotNull(ourAudioSource);
Assert.IsNotNull(bing);
Assert.IsNotNull(crash);
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("column"))
{
ourAudioSource.PlayOneShot(bing);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("ground") ||
collision.gameObject.CompareTag("pipe"))
{
ourAudioSource.PlayOneShot(crash);
}
}
Remember to add the two audio clips in the editor. The Assert.IsNotNull() calls are optional, but help you to find uninitialized fields easily.

Audio source does not want to work even though it is "triggered" by collision box

I have a weird problem. I want to trigger a audio file with a collision box. The Debug Log confirms that the audio source is triggered, but it would play the audio. What could possibly be the reason here?
I have attached an audio listener to my camera, and I attached an audio source to an object that is quipped with this code:
using UnityEngine;
[CreateAssetMenu(menuName = "ScriptableCookbook/Actions/PlayAudioAction")]
public class PlayAudioAction : ScriptableAction
{
[SerializeField] private AudioClip clipToPlay = null;
private AudioSource audioSource;
public override void PerformAction(GameObject obj)
{
audioSource = obj.AddComponent<AudioSource>();
audioSource.clip = clipToPlay;
audioSource.playOnAwake = false;
audioSource.spatialBlend = 1;
audioSource.Play();
}
public override void StopAction(GameObject gameObject)
{
if (audioSource != null)
{
audioSource.Stop();
}
}
}
These are the audio settings in the inspector of the object that has a box collider (is trigger) and these sound settings:
And this is the sound itself:
You are too far away!
You enabled SpatialBlend = 1
And in the Inspector you can see the falloff curve and the red line is where your audio listener is at => far too far away to really hear anything of the sound
You'll have to edit that roll-off in order to allow your audio listener to hear the sounds from further away.
In general: Is there a reason why adding that AudioSource component on demand?
Rather already add it on your object right from the beginning, adjust the settings correctly and in your code only do
public override void PerformAction(GameObject obj)
{
audioSource = obj.GetComponent<AudioSource>();
if(audioSource) audioSource.Play();
}
public override void StopAction(GameObject gameObject)
{
if (audioSource)
{
audioSource.Stop();
}
}

Unity3D playing sound when Player collides with an object with a specific tag

I using Unity 2019.2.14f1 to create a simple 3D game.
In that game, I want to play a sound anytime my Player collides with a gameObject with a specific tag.
The MainCamera has an Audio Listener and I am using Cinemachine Free Look, that is following my avatar, inside the ThridPersonController (I am using the one that comes on Standard Assets - but I have hidden Ethan and added my own character/avatar).
The gameObject with the tag that I want to destroy has an Audio Source:
In order to make the sound playing on the collision, I started by creating an empty gameObject to serve as the AudioManager, and added a new component (C# script) to it:
using UnityEngine.Audio;
using System;
using UnityEngine;
public class AudioManager : MonoBehaviour
{
public Sound[] sounds;
// Start is called before the first frame update
void Awake()
{
foreach (Sound s in sounds)
{
s.source = gameObject.AddComponent<AudioSource>();
s.source.clip = s.clip;
s.source.volume = s.volume;
s.source.pitch = s.pitch;
}
}
// Update is called once per frame
public void Play (string name)
{
Sound s = Array.Find(sounds, sound => sound.name == name);
s.source.Play();
}
}
And created the script Sound.cs:
using UnityEngine.Audio;
using UnityEngine;
[System.Serializable]
public class Sound
{
public string name;
public AudioClip clip;
[Range(0f, 1f)]
public float volume;
[Range(.1f, 3f)]
public float pitch;
[HideInInspector]
public AudioSource source;
}
After that, in the Unity UI, I went to the Inspector in the gameObject AudioManager, and added a new element in the script that I named: CatchingPresent.
On the Third Person Character script, in order to destroy a gameObject (with a specific tag) when colliding with it, I have added the following:
void OnCollisionEnter(Collision other)
{
if (other.gameObject.CompareTag("Present"))
{
Destroy(other.gameObject);
count = count - 1;
SetCountText();
}
}
It is working properly as that specific object is disappearing on collision. Now, in order to play the sound "CatchingPresent" anytime the Player collides with the object with the tag, in this case, Present, I have tried adding the following to the if in the OnCollisionEnter:
FindObjectOfType<AudioManager>().Play("CatchingPresent");
But I get the error:
The type or namespace name 'AudioManager' could not be found (are you
missing a using directive or an assembly reference?)
AudioManager.instance.Play("CatchingPresent");
But I get the error:
The name 'AudioManager' does not exist in the current context
As all the compiler errors need to be fixed before entering the Playmode, any guidance on how to make the sound playing after a collision between the player and the gameObject with the tag Present is appreciated.
Edit 1: Assuming that it is helpful, here it goes the full ThirdPersonUserControl.cs:
using System;
using UnityEngine;
using UnityEngine.UI;
using UnityStandardAssets.CrossPlatformInput;
namespace UnityStandardAssets.Characters.ThirdPerson
{
[RequireComponent(typeof (ThirdPersonCharacter))]
public class ThirdPersonUserControl : MonoBehaviour
{
public Text countText;
public Text winText;
private int count;
private ThirdPersonCharacter m_Character; // A reference to the ThirdPersonCharacter on the object
private Transform m_Cam; // A reference to the main camera in the scenes transform
private Vector3 m_CamForward; // The current forward direction of the camera
private Vector3 m_Move;
private bool m_Jump; // the world-relative desired move direction, calculated from the camForward and user input.
private void Start()
{
count = 20;
SetCountText();
winText.text = "";
// get the transform of the main camera
if (Camera.main != null)
{
m_Cam = Camera.main.transform;
}
else
{
Debug.LogWarning(
"Warning: no main camera found. Third person character needs a Camera tagged \"MainCamera\", for camera-relative controls.", gameObject);
// we use self-relative controls in this case, which probably isn't what the user wants, but hey, we warned them!
}
// get the third person character ( this should never be null due to require component )
m_Character = GetComponent<ThirdPersonCharacter>();
}
private void Update()
{
if (!m_Jump)
{
m_Jump = CrossPlatformInputManager.GetButtonDown("Jump");
}
}
// Fixed update is called in sync with physics
private void FixedUpdate()
{
// read inputs
float h = CrossPlatformInputManager.GetAxis("Horizontal");
float v = CrossPlatformInputManager.GetAxis("Vertical");
bool crouch = Input.GetKey(KeyCode.C);
// calculate move direction to pass to character
if (m_Cam != null)
{
// calculate camera relative direction to move:
m_CamForward = Vector3.Scale(m_Cam.forward, new Vector3(1, 0, 1)).normalized;
m_Move = v*m_CamForward + h*m_Cam.right;
}
else
{
// we use world-relative directions in the case of no main camera
m_Move = v*Vector3.forward + h*Vector3.right;
}
#if !MOBILE_INPUT
// walk speed multiplier
if (Input.GetKey(KeyCode.LeftShift)) m_Move *= 0.5f;
#endif
// pass all parameters to the character control script
m_Character.Move(m_Move, crouch, m_Jump);
m_Jump = false;
}
void OnCollisionEnter(Collision other)
{
if (other.gameObject.CompareTag("Present"))
{
Destroy(other.gameObject);
count = count - 1;
SetCountText();
//FindObjectOfType<AudioManager>().Play("CatchingPresent");
AudioManager.instance.Play("CatchingPresent");
}
}
void SetCountText()
{
countText.text = "Missing: " + count.ToString();
if (count == 0)
{
winText.text = "You saved Christmas!";
}
}
}
}
Edit 2: Hierarchy in Unity:
Reformulated the approach that I was following and solved the problem by simply adding an Audio Source to the ThirdPersonController (with the AudioClip that I wanted to call) and added GetComponent<AudioSource>().Play(); to the if statement as it follows:
void OnCollisionEnter(Collision other)
{
if (other.gameObject.CompareTag("Present"))
{
Destroy(other.gameObject);
count = count - 1;
SetCountText();
GetComponent<AudioSource>().Play();
}
}
Importing your scripts myself works without any issues when using FindObjectOfType<AudioManager>().Play("CatchingPresent");. Try reimporting your scripts from the editor (right click in the project folder > reimport all. this might take a while depending on the size of your project)
to use AudioManager.instance.Play("CatchingPresent"); you would first need to create a static variable that holds instance like this (this only works as a singleton, and will break if multiple AudioManager's are in the scene):
public class AudioManager : MonoBehaviour
{
//Create a static AudioManager that will hold the reference to this instance of AudioManager
public static AudioManager Instance;
public Sound[] sounds;
//Assign Instance to the instance of this AudioManager in the constructor
AudioManager()
{
Instance = this;
}
// Rest of the AudioManager code
}
Doing it like this, and using the rest of your code also works for me.

Audio not playing when ball enters the trigger

i have a game like the Rooltheball in unitys tutorials, and i want to play a sound when my ball hits the peaks, the thing is that i already tried everything, i basicly added a audioListener in my mainCamera, and added a audioSource and audioClip in the gameobject i want to detect the trigger, here is the code i did:
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class colisaoPicos : MonoBehaviour {
Manager gameManager;
public AudioClip impact;
private AudioSource audio;
void Start()
{
gameManager = GameObject.Find ("GameController").GetComponent<Manager> ();
}
void OnTriggerEnter(Collider c)
{
if (c.gameObject.tag == "Player") {
AudioSource.PlayClipAtPoint (impact, transform.position);
gameManager.LifeDown();
}
}
}
One solution would be to add an audiosource on the ball, and make it play the clip each time you enter the trigger.
Just make the audio variable public, and drag the AudioSource into it in the inspector.
Second, but in my book, and uglier solution would be to make a gameobject spesifically for that purpose. Then put the gameobject at the spot, and play the sound.
But, as programmer said, you should check the trigger. Remember, one of the Game Objects has to contain a Rigidbody. (Is Kinematic can be active tho)
As my experience, the following code is always working:
public AudioSource soundToPlay;
void OnTriggerEnter(Collider c)
{
if (c.gameObject.tag == "Player") {
soundToPlay.Play ();
}
}
Do not try to use playOneShot, or play clip. Error happens.
Try this it will play the sound once if Trigger function is working in your case and do add AudioListener component with the trigger gameobject.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class colisaoPicos : MonoBehaviour {
Manager gameManager;
public AudioClip impact;
private AudioSource audio;
void Start()
{
audio=GetComponent<AudioSource>();
gameManager = GameObject.Find ("GameController").GetComponent<Manager();
}
void OnTriggerEnter(Collider c)
{
if (c.gameObject.tag == "Player") {
audio.PlayOneShoot(impact);
gameManager.LifeDown();
}
}
}

Categories