Unity中音乐播放器的问题

时间:2019-10-09 09:53:19

标签: c# unity3d

所以我一直在Unity中开发音乐播放器。它从Unity中的数组获取音频片段,并且随机数生成器选择介于0和Unity中设置的大小之间的片段。但是,没有什么可以阻止它连续两次选择相同的编号(因此是同一首歌曲),这是我不希望的。我一直在尝试一些事情,但最终出现了NullReferenceException。如果您想看看,我将不胜感激!

代码:

using System.Collections;
using UnityEngine;

public class MusicPlayer : MonoBehaviour
{
    #region Variables

    //Variables needed for this code
    public AudioClip[] clips;

    private AudioSource audioSource;

    string currentTitle = "";

    #endregion

    #region Start Void
    // Start is called before the first frame update
    void Start()
    {
        //Finds AudioSource in the unity editor and turns off the "loop" function.
        audioSource = FindObjectOfType<AudioSource>();
        audioSource.loop = false;
    }
    #endregion

    #region Private AudioClip
    //The code below will grab a random audio clip between 0 and the amount set in the Unity Editor.
    private AudioClip GetRandomClip()
    {
        return clips[Random.Range(0, clips.Length)];

    }
    #endregion

    #region Update Void
    // Update is called once per frame
    void Update()
    {


        if (audioSource.clip.name.Length >= 0)
        {
            currentTitle = audioSource.clip.name;
        }

        if (!audioSource.isPlaying)
        {
            var nextTitle = currentTitle;
            ulong index = 0;
            while (nextTitle == currentTitle)
            {
                index = (ulong) Random.Range(0, clips.Length);
                nextTitle = clips[index].name;
            }
            audioSource.Play(index);
        }


    }
    #endregion
}

回到我的代码中,为将来的事情做准备,例如从多个数组中调用音频剪辑,并在Silleknarf和derHugo的帮助下,我完成了工作。非常感谢大家。这是我最后得到的代码:

/*
    AudioPlayer.cs
    RTS Game

    Created by Robin den Ambtman on 17-06-2019
    Copyright © Robinblitz. All rights reserved.
*/

using System.Collections;
using UnityEngine;
using System.Linq;

public class AudioPlayer : MonoBehaviour
{
    #region Variables

    //Variables needed for this code

    [Header("Sound arrays")]
    public AudioClip[] musicClips;
    [Space(10)]
    public AudioClip[] announcerClips;
    [Space(10)]
    public AudioClip[] TBDClips;

    [Header("Effect/Music sources")]
    public AudioSource effectAudioSource;
    public AudioSource musicAudioSource;

    #endregion

    #region Start Void
    // Start is called before the first frame update
    void Start()
    {
        //Finds AudioSource in the unity editor and turns off the "loop" function.
        musicAudioSource.loop = false;
        Random.InitState((int)System.DateTime.Now.Ticks);
    }
    #endregion

    #region Music RNG
    //The code below will grab a random audio clip between 0 and the amount of clips set in the Unity Editor.
    private AudioClip GetRandomMusicClip()
    {

        // This returns only those clips that are not the currenty played one
        var filteredClips = musicClips.Where(c => c != musicAudioSource.clip).ToArray();

        return filteredClips[Random.Range(0, filteredClips.Length)];
    }
    #endregion

    #region Update Void
    // Update is called once per frame
    void Update()
    {
        //If the audio source is playing it will grab the song that's picked out by GetRandomClip() and plays it.
        if (!musicAudioSource.isPlaying)
        {
            var newTitle = GetRandomMusicClip();
            musicAudioSource.clip = newTitle;
            musicAudioSource.Play();
        }

        //Piece of code as a test to play a specific audio clip on key press.
        if (Input.GetKeyDown(KeyCode.Space))
        {
            effectAudioSource.PlayOneShot(effectAudioSource.clip, 0.7f);
        }
    }
    #endregion
}

2 个答案:

答案 0 :(得分:5)

other answer中已经提到,AudioSource.Play(ulong)的参数是

  

延迟
  不推荐使用。

     

假设采样率为44100Hz(表示Play(44100)会将播放延迟恰好1秒钟),采样数会延迟。

所以您要做的是

audioSource.clip = newClip;
audioSource.Play();

那么我宁愿建议使用Linq Where并事先过滤掉不需要的(=当前正在播放的)剪辑,而不会像任何while循环那样

using System.Linq;

...

private AudioClip GetRandomClip()
{
    // This returns only those clips that are not the currenty played one
    var filteredClips = clips.Where(c => c != audioSource.clip).ToArray();

    return filteredClips[Random.Range(0, filteredClips.Length)];
}

void Update()
{
    if (!audioSource.isPlaying)
    {
        var newTitle = GetRandomClip();
        audioSource.clip = newTitle;
        audioSource.Play();
    }
}

答案 1 :(得分:1)

您似乎没有使用audioSource.clip属性为audioSource设置剪辑。将string currentTitle变量更改为AudioClip currentClip,然后在进行相等比较时仅使用currentClip.title属性,可能会更容易。然后,在调用audioSource.Play()方法之前的最后,可以如下设置剪辑:audioSource.clip = nextTitle;

要注意的另一件事是,audioSource.Play方法的参数是延迟而不是要播放的剪辑的索引,因此您需要先设置剪辑,甚至可能不需要传递参数到audioSource.Play方法。