我用C#制作了一个小团体游戏。
到目前为止,我已设法设计关卡并完成一些基本的脚本编写。
目前我有一个触发器,它会产生一个对象并希望它在用户输入后播放和音源。但是,因为我希望它是一个跳跃恐慌,触发器非常小,目前声音只播放IF我留在触发器。
我的代码如下:
using UnityEngine;
using System.Collections;
public class Spawner : MonoBehaviour {
public GameObject monster;
public AudioSource aud;
public AudioClip piano;
void Start ()
{
monster.SetActive (false);
aud = monster.GetComponent<AudioSource>();
}
void OnTriggerEnter(Collider other){
if (other.CompareTag ("Player")) {
monster.SetActive (true);
AudioSource.PlayClipAtPoint(piano, monster.transform.position);
}
}
void OnTriggerExit(Collider other){
if (other.CompareTag ("Player")) {
monster.SetActive (false);
}
Destroy (this.gameObject);
}
}
我想知道是否有一种方法可以在人们触发后保持声音播放。
谢谢!
答案 0 :(得分:5)
附加的GameObject音频在音频播放结束前被销毁。使用AudioSource.PlayClipAtPoint
将创建并销毁Audiosource
,这会使aud
的缓存变得无用。此外,如果您有太多触发游戏对象,由于GC
,这将会很慢。使用Coroutine
并等待音频完成播放然后销毁gameObject
。
public GameObject monster;
public AudioSource aud;
public AudioClip piano;
void Start()
{
monster.SetActive(false);
aud = GetComponent<AudioSource>();
}
void OnTriggerEnter(Collider other)
{
if (aud.isPlaying)
{
return; //Exit if Audio is already playing
}
if (other.CompareTag("Player"))
{
monster.SetActive(true);
aud.PlayOneShot(piano);
}
}
void OnTriggerExit(Collider other)
{
if (other.CompareTag("Player"))
{
monster.SetActive(false);
}
StartCoroutine(waitForAudioThenDestroy());
}
IEnumerator waitForAudioThenDestroy()
{
//Wait until we are done playing
while (aud.isPlaying)
{
yield return null;//Don't freeze
}
//We are no longer playing audio so we can destroy this gameObject now
Destroy(this.gameObject);
}
答案 1 :(得分:2)
您的问题是,在声音播放完毕之前,您正在gameObject
功能中删除AudioSource
附加的OnTriggerExit
。解决此问题的一种简单方法是将AudioSource
附加到您的monster
,然后从那里访问它。这将有效,因为你不是在摧毁怪物。我认为您需要更改的是(在将AudioSource
移至检查员中的monster
之后):
void Start ()
{
monster.SetActive (false);
aud = monster.GetComponent<AudioSource>();
}
另一种更快速的排序方法是在OnTriggerEnter
方法中调用PlayClipAtPoint
:
IEnumerator OnTriggerEnter(Collider other){
if (other.CompareTag ("Player")) {
monster.SetActive (true);
AudioSource.PlayClipAtPoint(piano, monster.transform.position);
}
}
由于这是一种静态方法,因此您可以完全删除aud
音频源。 AudioSource.PlayClipAtPoint
通过在您指定的点(AudioSource
)中实例化世界中的新monster.transform.position
组件,播放指定的剪辑(piano
),然后删除{剪辑完成播放后{1}}。
编辑:另外,我认为您的AudioSource
方法不需要OnTriggerEnter
的返回类型,因为您没有在方法的任何位置使用IEnumerator
关键字。您只需将其更改为yield
返回类型即可。但这不会影响代码的功能。
Edit2:我愚蠢地忽略了你将怪物设置为不活动的事实。我认为在这种情况下,您最好的选择是使用void
。