Unity:在所有场景上管理AudioManager

时间:2019-12-23 17:44:26

标签: c# unity3d

我使用以下代码创建了一个c0, c1 = map(pd.Series, zip(*[(a, b) for s, c in df.groupby('sport')['Country(s)'] for a, b in product(c, c)])) pd.crosstab(c0, c1).rename_axis(None).rename_axis(None, axis=1) Australia Brazil South_Africa Uk Australia 3 0 1 3 Brazil 0 2 1 2 South_Africa 1 1 2 2 Uk 3 2 2 5

AudioManager

只要我在定义using System; using UnityEngine.Audio; using UnityEngine; public class AudioManager : MonoBehaviour { public Sound[] sounds; public static AudioManager instance; void Awake() { if (instance == null) { instance = this; } else { Destroy(gameObject); return; } DontDestroyOnLoad(gameObject); } public void Play(SoundType soundType) { Sound s = Array.Find(this.sounds, sound => sound.soundType == soundType); s.source = gameObject.AddComponent<AudioSource>(); s.source.clip = s.clip; // We define volume and pitch here to be able to change them in real time s.source.volume = s.volume; s.source.pitch = s.pitch; s.source.Play(); } } (包含此gameObject)的场景中启动它,它的效果就很好。 但是,出于某些调试目的,我确实单独启动了某些场景,并且未定义包含MonoBehaviour的{​​{1}}。我应该如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

您可以使用自动构造的单例。第一次调用AudioManager.Instance时,它将生成一个新的游戏对象并将AudioManager脚本附加到该对象。

public class AudioManager : MonoBehaviour
{
    static AudioManager instance;
    public static AudioManager Instance => instance ?? (instance = new GameObject("AudioManager", typeof(AudioManager)).GetComponent<AudioManager>());

    public void PlaySound(SoundType soundType)
    {
        Debug.Log("Play Sound: " + soundType);
    }
}

答案 1 :(得分:2)

所以有两个任务:

  • 您需要AudioManager或更准确地说是AudioSource实例,以便可以在任何场景中访问/实例化
  • 您要填充List<Audio clip>

为了使两者融合在一起,我将使用ScriptableObject

[CreateAssetMenu]
public class AudioData : ScriptableObject
{
    public List<Sound> sounds = new List<Sound>();
}

通过右键单击资产→创建 AudioData

创建实例

您可以在此处填充Sounds的列表。

然后,我将直接使用您的Singleton进行惰性实例化,以便在场景中找不到甚至与[RuntimeInitializeOnLoadMethod]组合的情况下初始化一个实例。

  

标记为[RuntimeInitializeOnLoadMethod]的方法在游戏加载后被调用。

在完成所有Awake调用之后将调用此方法,因此该实例要么存在,要么立即创建。

例如

public class AudioManager : MonoBehaviour
{
    // if you have it in the scene you can reference these right away
    [SerializeField] private AudioData audioData;
    [SerializeField] private AudioSource audioSource;

    // backing field for actually store the Singleton instance
    private static AudioManager _instance;

    // public access for the Singleton
    // and lazy instantiation if not exists
    public static AudioManager Instance
    {
        get
        {
            // if exists directly return
            if(_instance) return instance;

            // otherwise search it in the scene
            _instance = FindObjectOfType<AudioManager>();

            // found it?
            if(_instance) return instance;

            // otherwise create and initialize it
            CreateInstance();

            return _instance;
        }
    }

    private void Awake()
    {
        if (_instance && _instance != this)
        {
            Destroy(gameObject);
            return;
        }

        InitializeInstance(this);
    }

    [RuntimeInitializeOnLoadMethod]
    private static void CreateInstance()
    {
        // skip if already exists
        if(_instance) return;

        InitializeInstance(new GameObject (nameof(AudioManager)).AddComponent<AudioManager>());         
    }

    private static void InitializeInstance(AudioManager instance)
    {
        _instance = instance;
        DontDestroyOnLoad(gameObject);
        if(!_instance.audioSource) _instance.audioSource = _instance.AddComponent<AudioSource>();

        if(_instance.audioData) return;

        var audioDatas = Resources.FindObjectsOfType<AudioData>();
        if(audioDatas.Length == 0)
        {
            Debug.LogError("No Instance of AudioData found! Don't forget to create that ScriptableObject!");
            return;
        }

        _instance.audioData = audioDatas[0];
    }

    public void Play(SoundType soundType)
    {
        Sound s = audioData.sounds.First(sound => sound.soundType == soundType);

        s.source = audioSource;
        s.source.clip = s.clip;

        // We define volume and pitch here to be able to change them in real time
        s.source.volume = s.volume;
        s.source.pitch = s.pitch;
        s.source.Play();
    }
}

答案 2 :(得分:0)

使AudioManager单身,并在需要它的每个场景中访问它。
使用以下模式:http://wiki.unity3d.com/index.php/Singleton

请注意,您不想要执行

s.source = gameObject.AddComponent<AudioSource>();

每次玩。在播放声音时,您将获得一堆AudioSources。您应该检查是否存在,然后根据需要创建它。另外,如果一次只播放一种声音,则只能使用一个音频源。