Unity播放AudioClip Null参考

时间:2019-08-03 16:42:37

标签: c# unity3d

我有一个AudioManager.cs脚本,可以使用Singleton模式。从我的SplashController.cs脚本中,我尝试播放音频剪辑AudioManager.Instance.PlayMusic(intro);,但此行NullReferenceException: Object reference not set to an instance of an object出现错误,因为我做了Debug.Log(introClip);

,音频文件确实存在

我已经检查了游戏正在运行,并且musicSource = gameObject.AddComponent<AudioSource>() as AudioSource;AudioManager创建了

在播放音频剪辑之后创建AudioSource;可能是一个计时问题。我之前已经运行过类似的代码,但是还没有遇到这个问题。

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

2 个答案:

答案 0 :(得分:1)

您可以尝试使用懒惰的单身人士:

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

答案 1 :(得分:0)

您的方法存在的问题是,派生类中的void Awake方法将覆盖基类protected void Awake中的Singleton<>

要使您的方法可行,您需要从新方法中调用基本方法:

void Awake()
{
    base.Awake();
    // The rest of AudioManager.Awake() here.
}