Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 播放音频并播放更多_C#_Unity3d - Fatal编程技术网

C# 播放音频并播放更多

C# 播放音频并播放更多,c#,unity3d,C#,Unity3d,我正在用C#在unity 5中制作一个小游戏 到目前为止,我成功地设计了这个级别,并完成了一些基本的脚本编写 目前,我有一个触发器,它生成一个对象,并希望在用户进入后播放该对象和音频源。然而,因为我希望它是一个跳跃的恐惧,触发器是非常小的,目前的声音只会播放,如果我留在触发器 我的代码如下: using UnityEngine; using System.Collections; public class Spawner : MonoBehaviour { public GameOb

我正在用C#在unity 5中制作一个小游戏

到目前为止,我成功地设计了这个级别,并完成了一些基本的脚本编写

目前,我有一个触发器,它生成一个对象,并希望在用户进入后播放该对象和音频源。然而,因为我希望它是一个跳跃的恐惧,触发器是非常小的,目前的声音只会播放,如果我留在触发器

我的代码如下:

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

}
使用UnityEngine;
使用系统集合;
公共类产卵器:单行为{
公共游戏对象怪物;
公共音频源aud;
公共录音带钢琴;
无效开始()
{
monster.SetActive(false);
aud=monster.GetComponent();
}
无效对撞机(对撞机其他){
if(other.CompareTag(“玩家”)){
monster.SetActive(true);
音频源。播放剪辑点(钢琴、怪物、变换、位置);
}
}
void OnTriggerExit(碰撞器其他){
if(other.CompareTag(“玩家”)){
monster.SetActive(false);
}
摧毁(这个游戏对象);
}
}
我想知道是否有一种方法可以即使在人们离开扳机后仍保持声音播放


谢谢

您的问题是,您正在删除
音频源
OnTriggerExit
功能中附加的
游戏对象
,然后声音才能播放完毕。解决此问题的一个简单方法是将
音频源
连接到您的
怪物
,然后从那里访问它。这将起作用,因为你没有摧毁怪物。我认为您需要更改的只是以下内容(在您将
音频源
移动到inspector中的
怪物
之后):

由于这是一种静态方法,因此您可以完全删除
aud
音频源。
AudioSource.PlayClipAtPoint
的工作原理是在您指定的点(
monster.transform.position
)实例化世界上新的
AudioSource
组件,播放指定的剪辑(
piano
),然后在剪辑播放完成后删除
AudioSource

编辑:另外,我不认为你的
OnTriggerEnter
方法需要
IEnumerator
的返回类型,因为你没有在方法的任何地方使用
yield
关键字。您可以简单地将其更改为具有
void
返回类型。无论如何,这不会影响代码的功能


Edit2:我愚蠢地忽略了一个事实,即你正在将怪物设置为不活动状态。我认为在这种情况下,您最好的选择是使用
PlayClipAtPoint

在音频播放结束之前,附加到的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);
}
公共游戏对象怪物;
公共音频源aud;
公共录音带钢琴;
void Start()
{
monster.SetActive(false);
aud=GetComponent();
}
无效对撞机(对撞机其他)
{
如果(辅助显示)
{
return;//如果音频已在播放,则退出
}
如果(其他比较标记(“玩家”))
{
monster.SetActive(true);
钢琴伴奏(钢琴);
}
}
void OnTriggerExit(碰撞器其他)
{
如果(其他比较标记(“玩家”))
{
monster.SetActive(false);
}
start例程(waitForAudioThenDestroy());
}
IEnumerator waitForAudioThenDestroy()
{
//等我们玩完再说
while(aud.isplay)
{
yield return null;//不冻结
}
//我们不再播放音频,因此现在可以销毁此游戏对象
摧毁(这个游戏对象);
}

谢谢您的回复,但一旦我离开触发器,音频仍会停止。您尝试了哪种方法?如果您使用
PlayClipAtPoint
方法,则这是您需要在代码中更改的唯一一行。@Kingspud我已编辑了我的答案。第二部分是有效的部分。i、 在函数定义中的“@Kingspud Change
IEnumerator
for
void
”之后添加“另一种更快的排序方法”。谢谢您的回复,我尝试了上述方法,但它不会破坏触发器。如果我向后走,怪物会重生,声音会重放。如果这种情况在游戏中只发生一次,只使用OnTiggerEnter并在那里启动协同程序不是更好吗?这是一个简单的脚本,应该可以工作。你可能在做别的事情。放置
Debug.Log(“等待音频完成”)
while(aud.isplay)
循环中。将
Debug.Log(“完成播放”)
放在
销毁(此.gameObject)之前然后仅使用一个繁殖器脚本实例运行此脚本。将您的日志粘贴到pastebin.com上,并将我链接到那里。@GJTT1如果这是他遇到的问题,他应该将if
(aud.isPlaying){return;//如果音频已经播放,则退出}
添加到
void OnTriggerEnter(Collider other){
在该函数中的任何其他代码之前。只要修改我的答案,使其包含修复,如果这是他遇到的问题。是的,我认为这将使您的答案完整。@Kingspud检查编辑并接受此答案,如果它有效!此问题“可怕”!:)由@GJT1提供的第一个答案似乎对我有用。我有一个错误,它没有意义,但不会导致游戏崩溃。你有很大的问题。(1)制作一个全新的游戏对象,称为“惊吓声音”。(2)在“惊吓声音”中,有音频源。(3)在“惊吓声音”中,有一个名为ScareHandler的小脚本,它不执行任何操作
IEnumerator OnTriggerEnter(Collider other){
    if (other.CompareTag ("Player")) {
        monster.SetActive (true);
        AudioSource.PlayClipAtPoint(piano, monster.transform.position);
    }

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