简体   繁体   English

Unity播放AudioClip Null参考

[英]Unity playing AudioClip Null Reference

I have an AudioManager.cs script which I use the Singleton pattern with. 我有一个AudioManager.cs脚本,可以使用Singleton模式。 From my SplashController.cs script I an trying to play an audio clip AudioManager.Instance.PlayMusic(intro); 从我的SplashController.cs脚本中,我尝试播放音频剪辑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); 但此行出现错误NullReferenceException: Object reference not set to an instance of an object音频文件确实存在,因为我执行了Debug.Log(introClip);

I have checked while the game is running and the musicSource = gameObject.AddComponent<AudioSource>() as AudioSource; 我已经检查了游戏正在运行,并且将musicSource = gameObject.AddComponent<AudioSource>() as AudioSource; is created by the AudioManager AudioManager创建

Could it be a timing issue where the AudioSource; AudioSource;是否可能是时间问题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 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 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 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);
        }
    }
}

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

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. 您的方法的问题在于,派生类中的void Awake方法将覆盖基Singleton<>类中protected void Awake

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM