I have an AudioManager for my Game. When I try to play a clip on a NPC it doesn't get played. The script itself works because the background music is playing properly.
The code of the relevant parts:
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Random = UnityEngine.Random;
public class AudioManager : MonoBehaviour
{
private AudioSource audioSource;
private AudioSource backgroundPlayer;
private Dictionary<string, Sound> audioClips;
public List<Sound> background;
void Start()
{
Sound current = background[background.Count-1];
backgroundPlayer.clip = current.clip;
backgroundPlayer.volume = current.volume;
backgroundPlayer.pitch = current.pitch;
backgroundPlayer.Play(); //works absolutely fine
}
public void SetCurrentSource(AudioSource a)
{
audioSource = a;
}
public void Play(string name, string NPCSpeaker)
{
string actualName = name "_" NPCSpeaker;
if (audioClips.ContainsKey(actualName))
{
audioSource.clip = audioClips[actualName].clip;
audioSource.volume = audioClips[actualName].volume;
audioSource.pitch = audioClips[actualName].pitch;
Debug.Log("Start Audio " audioSource.clip);
audioSource.Play();
Debug.Log(audioSource.isPlaying);
}
else
{
Debug.LogWarning("AudioClip with name " actualName " is not found." );
}
}
And the Sound Class:
public class Sound
{
public string name;
public AudioClip clip;
[Range(0f, 1f)]
public float volume;
[Range(.1f, 3f)]
public float pitch;
}
Before I call Play()
, I always call setCurrentSource()
because the audioSource
is the current NPC in the conversation.
Clip, volume and pitch are set correctly and are not null.
I found out, when I debug it, set a breakpoint in Play()
somewhere and go to the point of calling audioSource.Play()
, then open the inspector to view the object informations in VS Code, it will play the audio. If i just wait at audioSource.Play()
it doesn't.
The Debug statement Debug.Log(audioSource.isPlaying)
returns false.
As said I can hear the music, so Editor isn't muted. Gameobject with the AudioSource Component is activated.
Edit: Creating the AudioClips:
void Awake()
{
backgroundPlayer = gameObject.GetComponent<AudioSource>();
createAudioClips();
audioClips = new Dictionary<string, Sound>();
foreach (Sound s in sounds)
{
audioClips.Add(s.name, s);
}
}
private void createAudioClips()
{
string rel = Application.streamingAssetsPath "/Audio/";
string[] paths = new string[] { rel "Brian", rel "Matthew", rel "Russell", rel "Leader", rel "Scientist" };
foreach (string p in paths)
{
foreach (string fileName in Directory.GetFiles(p))
{
if (Path.GetExtension(fileName) == ".mp3")
{
if (p == rel "Scientist")
{
CreateNewSound(fileName, true);
}
else
{
CreateNewSound(fileName, false);
}
}
}
}
}
private void CreateNewSound(string filename, bool isScientist)
{
WWW request = new WWW(filename);
string[] subs = filename.Split('\\');
Sound newSound = new Sound();
newSound.name = Path.GetFileNameWithoutExtension(filename);
newSound.clip = request.GetAudioClip();
if (isScientist)
{
newSound.volume = 1f;
}
else
{
newSound.volume = 0.5f;
}
newSound.pitch = 1f;
sounds.Add(newSound);
}
The Soundfiles are .mp3 and are in the StreamingAssets Folder.
CodePudding user response:
You just edited to show how you're loading the audio clips and I don't know if you're actually getting anything out of this. It looks like you've got two different mechanisms going at the same time. On the one hand you're calling:
foreach (string fileName in Directory.GetFiles(p))
This looks like you're trying to get to local files because you cannot use the Directory
class to list files of a Web directory. On the other hand, when you actually try to get the clip, you're calling:
WWW request = new WWW(filename);
newSound.clip = request.GetAudioClip();
Which then looks like you're trying to do something web-related. But your filename
is the output of Directory.GetFiles()
which, again, is not for web things.
Since you're saying your debug statements are working when you try to play the clip:
The Debug statement Debug.Log(audioSource.isPlaying) returns false.
I'm going to assume that you're actually building your Dictionary, which means all the rest of the clip-loading code is probably firing. This makes me think that your audio clips are not actually getting loaded and you're probably trying to play a null
clip. This would be why you're not hearing anything.
As a troubleshooting step, try the following for your CreateNewSound
method:
private void CreateNewSound(string filename, bool isScientist)
{
WWW request = new WWW(filename);
string[] subs = filename.Split('\\');
Sound newSound = new Sound();
newSound.name = Path.GetFileNameWithoutExtension(filename);
newSound.clip = request.GetAudioClip();
// New Debug statement:
if(newSound.clip == null)
{
Debug.LogErrorFormat("Failed to load a clip for {0}", filename);
}
// End new Debug statement
if (isScientist)
{
newSound.volume = 1f;
}
else
{
newSound.volume = 0.5f;
}
newSound.pitch = 1f;
sounds.Add(newSound);
}
See if this starts giving you Debug Errors that it's not loading the clip.
CodePudding user response:
[SOLVED] The problem is in the Loading part. With WWW the sounds didn't got created right. I changed createAudioClips() and createNewSound() to
private void createAudioClips()
{
string rel = "Audio";
string[] paths = new string[] { "Brian", "Matthew", "Russell", "Leader", "Scientist" };
foreach (string p in paths)
{
string abs = Path.Combine(rel, p);
var files = Directory.GetFiles(Path.Combine(Application.dataPath, "Resources", abs));
foreach (string fileName in files)
{
if (Path.GetExtension(fileName) == ".mp3")
{
if (p == rel "Scientist")
{
createNewSound(fileName, abs, true);
}
else
{
createNewSound(fileName, abs, false);
}
}
}
}
}
private void createNewSound(string filename, string abs, bool isScientist)
{
Sound newSound = new Sound();
newSound.name = Path.GetFileNameWithoutExtension(filename);
string file = Path.Combine(abs, newSound.name);
newSound.clip = Resources.Load(file) as AudioClip;
if (isScientist)
{
newSound.volume = 1f;
}
else
{
newSound.volume = 0.5f;
}
newSound.pitch = 1f;
sounds.Add(newSound);
}
It work fine now.