简体   繁体   English

Unity 中的音乐播放器问题

[英]Issues with music player in Unity

So I've been working on a music player in Unity.所以我一直在 Unity 中开发音乐播放器。 It gets the audioclips from an array within Unity, and a random number generator picks a clip between 0 and the size set in Unity.它从 Unity 中的数组中获取音频剪辑,并且随机数生成器在 0 和 Unity 中设置的大小之间选择一个剪辑。 However, nothing stops it from picking the same number (and thus same song) twice in a row which is something I do not want.然而,没有什么能阻止它连续两次选择相同的数字(因此是相同的歌曲),这是我不想要的。 I've been trying a few things but ended up with a NullReferenceException.我一直在尝试一些事情,但最终得到了 NullReferenceException。 If you'd like to take a look I'd greatly appreciate it!如果您想看一看,我将不胜感激!

Code:代码:

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
}

Went back into my code to prepare it for future stuff as well like calling audio clips from multiple arrays and with the help of both Silleknarf and derHugo I got it worked out.回到我的代码中,为将来的事情做准备,比如从多个 arrays 调用音频剪辑,在 Silleknarf 和 derHugo 的帮助下,我把它解决了。 Thank you all so much.非常感谢大家。 Here is the code I ended up with:这是我最终得到的代码:

/*
    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
}

As already mentioed in the other answer the parameter of AudioSource.Play(ulong) is正如在另一个答案中已经提到的, AudioSource.Play(ulong)的参数是

delay延迟
Deprecated.已弃用。

Delay in number of samples, assuming a 44100Hz sample rate (meaning that Play(44100) will delay the playing by exactly 1 sec).采样数延迟,假设采样率为 44100Hz(意味着 Play(44100) 将延迟播放正好 1 秒)。

So what you want to do is所以你想做的是

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

Then I would rather suggest using Linq Where and filter the unwanted (= currently playing) clip out beforehand without any while -loop like然后我宁愿建议使用Linq Where并预先过滤掉不需要的(=当前正在播放的)剪辑,而不需要任何while -loop

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

It looks like you don't set the clip for the audioSource using the audioSource.clip property.看起来您没有使用audioSource.clip属性为 audioSource 设置剪辑。 Perhaps it would be easier to change the string currentTitle variable to be a AudioClip currentClip and then just use the currentClip.title property when doing the equality comparisons.也许将string currentTitle变量更改为AudioClip currentClip然后在进行相等比较时只使用currentClip.title属性会更容易。 Then at the end just before you call the audioSource.Play() method you can set the clip as follows: audioSource.clip = nextTitle;最后,在调用audioSource.Play()方法之前,您可以按如下方式设置剪辑: audioSource.clip = nextTitle; . .

Another thing to note is that the parameter to the audioSource.Play method is the delay rather than the index of the clip to play so you need to set the clip first and probably don't even need to pass a parameter to the audioSource.Play method.另外需要注意的是, audioSource.Play方法的参数是延迟而不是要播放的剪辑的索引,因此您需要先设置剪辑,甚至可能不需要将参数传递给audioSource.Play方法。

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

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