所以我一直在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
}
答案 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
方法。