播放音频并播放更多

时间:2016-04-28 22:10:13

标签: c# unity3d

我用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);
    }

}

我想知道是否有一种方法可以在人们触发后保持声音播放

谢谢!

2 个答案:

答案 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