Reputation: 14151
I have an AudioManager.cs script which I use the Singleton pattern with. From my SplashController.cs script I an trying to play an audio clip AudioManager.Instance.PlayMusic(intro);
but I get an error with this line NullReferenceException: Object reference not set to an instance of an object
The audio files does exist because I do a Debug.Log(introClip);
I have checked while the game is running and the musicSource = gameObject.AddComponent<AudioSource>() as AudioSource;
is created by the AudioManager
Could it be a timing issue where the AudioSource;
is created after the audio clip is being played. I have run similar code before and I have not run onto this issue.
AudioManager.cs
using UnityEngine;
using System.Collections;
using UnityEngine.Audio;
public class AudioManager : Singleton<AudioManager>
{
[Header("Mixer Groups")]
public AudioMixer masterMixer;
public AudioMixerGroup masterGroup;//The master mixer group
public AudioMixerGroup musicGroup;//The music mixer group
public AudioMixerGroup sfxGroup; //The sfx mixer group
public int lowestDeciblesBeforeMute = -20;
AudioSource musicSource; //Reference to the generated music Audio Source
AudioSource musicSource2; //Reference to the generated music Audio Source
AudioSource sfxSource; //Reference to the generated sfx Audio Source
private float musicVolume = 1;
// Multiple musics
private bool firstMusicSourceIsActive;
#region Public Enums
public enum AudioChannel { Master, Music, Sfx }
#endregion Public Enums
void Awake()
{
//Generate the Audio Source "channels" for our game's audio
musicSource = gameObject.AddComponent<AudioSource>() as AudioSource;
musicSource2 = gameObject.AddComponent<AudioSource>() as AudioSource;
sfxSource = gameObject.AddComponent<AudioSource>() as AudioSource;
//Assign each audio source to its respective mixer group so that it is
//routed and controlled by the audio mixer
musicSource.outputAudioMixerGroup = musicGroup;
musicSource2.outputAudioMixerGroup = musicGroup;
sfxSource.outputAudioMixerGroup = sfxGroup;
// Make sure to enable loop on music sources
musicSource.loop = true;
musicSource2.loop = true;
}
// Play a single clip through the sound effects source.
public void PlaySfx(AudioClip clip)
{
sfxSource.PlayOneShot(clip);
}
// Play a single clip through the music source.
public void PlayMusic(AudioClip clip)
{
musicSource.clip = clip;
musicSource.Play();
}
}
SplashController.cs
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SplashController : MonoBehaviour {
public float waitTime = 5;
public AudioClip introClip;
// Use this for initialization
void Start () {
Debug.Log(introClip);
AudioManager.Instance.PlayMusic(introClip);
StartCoroutine(LoadMenu());
}
private IEnumerator LoadMenu()
{
yield return new WaitForSeconds(waitTime);
SceneManager.LoadScene(1);
}
}
Singleton.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
public static T Instance { get; private set; }
protected void Awake()
{
if (Instance == null)
{
Instance = this as T;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}
Upvotes: 0
Views: 2318
Reputation: 4092
The problem with your approach is that the void Awake
method in the derived class is overriding the protected void Awake
in the base Singleton<>
class.
To make your approach work, you need to call the base method from the new one:
void Awake()
{
base.Awake();
// The rest of AudioManager.Awake() here.
}
Upvotes: 0
Reputation: 4888
You could try using a lazy singleton:
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
protected static T instance;
public static T Instance
{
get
{
if (instance == null)
{
instance = (T)FindObjectOfType(typeof(T));
if (instance == null)
{
Log.Error("An instance of " + typeof(T) + " is needed in the scene, but there is none.");
}
}
return instance;
}
}
}
Upvotes: 1