【问题标题】:How to execute a sound when an object goes through another object?当一个物体穿过另一个物体时如何发出声音?
【发布时间】:2018-07-13 18:16:57
【问题描述】:

嘿 StackOverflow 社区,我正在制作我的第一款游戏,但遇到了问题。游戏是关于一个球躲避障碍物以达到关卡的终点。所以我的问题是每当球通过障碍物时我想实现“Woosh”声音。我创建了一个不可见的对象,它应该在球通过不可见对象时执行“Woosh”声音。

这些是“不可见”对象的设置:

如果您查看图像,您会发现有一个“Woosh”脚本,其中包含以下代码行:

using UnityEngine;

public class Woosh : MonoBehaviour
{
    void OnCollisionEnter(Collision collisionInfo)
    {
        if (collisionInfo.collider.tag == "Player")
        {
            FindObjectOfType<AudioManager>().Play("Woosh");
        }
    }
}

这段代码应该让不可见对象在与播放器发生碰撞时播放“Woosh”音频。但是,当我在游戏中尝试时,当我通过不可见的对象时,音频永远不会播放。

供您参考,我确实有一个音频管理器,其中包含我迄今为止实现的所有声音。可以在这里看到:

注意:所有其他声音都可以工作,但“Woosh”声音无效。

感谢任何帮助!

提前致谢, E.W

【问题讨论】:

  • 您确认您的OnCollisionEnter 方法被调用,并且标签等于“玩家”吗?你知道FindObjectOfType是否真的返回一个值吗?
  • 另外,你确认你的“Woosh”声音会播放吗?如果您用“Woosh”替换您的其他声音呼叫之一,它会播放吗?在这种情况下,您必须做的是检查导致播放声音的所有内容。不要只是自动假设声音或其设置是问题所在。
  • 嗨,吉姆,很抱歉我离开了一段时间。所以我尝试用另一种声音替换音频管理器中的“Woosh”声音,但这些声音都不起作用。另外,你能解释一下你在第一条评论中的意思吗?我是 Unity 的新手,这就是为什么。暂时我会寻找解决方案。再次感谢!
  • Jim 我想你可能已经找到了我的问题的答案,但我还没有完全弄清楚。所以基本上我将“void OnCollisionEnter(Collision collisionInfo)”更改为“(void OnCollisionEnter(Woosh collisionInfo)”。希望这是朝着正确方向迈出的一步?无论如何,右侧脚本中的“collisionInfo.collider”部分已用红色下划线:“if (collisionInfo.collider.tag == “玩家”)
  • 您是否在OnCollisionEnter 上设置了断点,或者弹出了一条消息,或者任何东西 可以向您证明正在调用该方法?您是否确定if 语句的计算结果为true,并且代码实际上调用了FindObjectOfType?您不能只假设问题出在“呜”声上。您可以通过将播放“ShatterSmall”的调用替换为“Woosh”来验证“Woosh”声音是否有效。如果声音播放,那么您就知道它有效并且您的问题出在其他地方。

标签: c# unity3d audio transparency


【解决方案1】:

评论不够。

我想告诉你的是,你不能自动假设问题出在“Woosh”声音上。这只是可能出错的事情之一。你有这个代码:

public class Woosh : MonoBehaviour
{
    void OnCollisionEnter(Collision collisionInfo)
    {
        if (collisionInfo.collider.tag == "Player")
        {
            FindObjectOfType<AudioManager>().Play("Woosh");
        }
    }
}

你的期望是当OnCollisionEnter被调用时,会播放“Woosh”的声音。你说声音没有播放,所以你必须找出问题所在。这是我要检查的:

  1. 你能在其他地方播放“Woosh”声音吗?您应该能够在程序中添加代码以播放“Woosh”声音。也许用“Woosh”替换播放“ShatterSmall”的代码。如果声音在那里没有播放,那么“Woosh”声音可能有问题,您需要修复它。如果声音确实在那里播放,那么还有其他问题。
  2. 如果“Woosh”在其他地方播放,但不在此代码中,那么您必须检查代码是否正在执行。如果您在调试器中运行此代码,请在 OnCollisionEnter 方法上放置一个断点以查看它是否被调用。如果它没有被调用,那么问题出在其他地方。如果您没有调试器,则可以输出某种消息,例如“嘿,我到了!”告诉你 OnCollisionEnter 函数实际上被调用了。
  3. 如果您要访问OnCollisionEnter,那么您需要检查collisionInfo.collider.tag 是否确实包含值“Player”。同样,使用某种输出函数来告诉您该变量中有什么。
  4. 如果是collisionInfo.collider.tag == "Player",则检查对FindObjectOfType&lt;AudioManager&gt; 的调用是否返回预期值。

你可以分解你的代码:

var mgr = FindObjectOfType<AudioManager>();
if (mgr == null)
{
    // some error here. Maybe throw an exception.
}
else
{
    // Make sure (somehow) that it's really the object you wanted
}
mgr.Play("Woosh");
  1. 如果以上内容告诉您您得到了正确的对象,那么可能是播放声音时出现了问题。 Play 会抛出异常吗?

我在这里要说明的一点是,调试涉及质疑您的所有假设,并进行测试以查看失败的地方。这最好使用调试器来完成,因为它可以让您逐步浏览代码以查看确切发生了什么。

如果您不知道如何使用调试器,现在是学习的最佳时机。它将为您节省的调试时间。

【讨论】:

  • 这真的很方便,每当我遇到问题时,我一定会按照这些步骤进行操作。非常感谢吉姆米歇尔!
【解决方案2】:

它不会发出声音,因为您的对撞机是触发器而不是碰撞,所以如果您禁用 Is Trigger 框,当您与它发生碰撞时会播放声音。

如果你想像触发器一样通过对撞机,你需要使用这个函数。

void OnTriggerEnter(Collider other) {}
void OnTriggerStay(Collider other) {}
void OnTriggerExit(Collider other) {}

编辑: 同样使用 FindObjectOfType 是一个昂贵的功能,只需将音频管理器设为 Singleton

【讨论】:

  • 你好,当我禁用“是触发器”框时,声音确实播放了!但是,障碍物不允许玩家通过。你的意思是我应该使用你上面写的函数来让玩家能够穿过物体吗?在此先感谢,E.W
  • 没错,你需要将对象保持为Trigger才能通过它,并且具有OnTrigger而不是OnCollision的功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多