【问题标题】:Unity 3D: what is the correct way to detect that the collision has already been processed for another collision participant?Unity 3D:检测碰撞已经为另一个碰撞参与者处理的正确方法是什么?
【发布时间】:2019-10-15 02:17:19
【问题描述】:

我有一个类CollisionHandler,它有OnCollisionEnter 方法。游戏中的每个可碰撞实体都有CollisionHandler作为一个组件。因此,当 2 个对象发生碰撞时,OnCollisionEnter 方法被调用两次,这没关系,因为损坏和其他事情是由于对象“A”接触对象“B”而处理的,反之亦然。

此外,每次碰撞都会产生闪光效果并播放撞击声,当然,每次碰撞也会播放两次这些效果。尽管它不会被玩家察觉,但它似乎并不正确。为了防止它,我想出了以下解决方案:我将当前帧号保存在另一个碰撞参与者中,这样它就会知道这些效果已经被第一个参与者播放了。

private void OnCollisionEnter(Collision collision)
{
    // Calculate the damage caused by `this.gameObject` to `collision.gameObject`.
    // ...

    // Play an impact sound and show a visual effect.
    if (thisObject.CollisionFrameId != Time.frameCount)
    {
        otherObject.CollisionFrameId = Time.frameCount;
        // play sound
        // show hit effect
    }
}

虽然它有效,但我不确定(我是 Unity 的新手)这是最佳实践,如果是,请提出其他可能的解决方案。

请注意,我没有问"Why is OnCollisionEnter getting called twice?"。我知道为什么会这样。我的问题是关于另一个的,虽然它确实提到了同一个函数的名称,但它仍然没有问同样的问题。

【问题讨论】:

  • 我在 5 分钟内想到的所有解决方案都包含一些我会阅读和比较的标志或值,以便知道其他人已经处理了这个冲突。而是存储当前时间/帧数听起来更合乎逻辑!所以我会说如果这已经可行,很好的解决方案;)
  • 如果您的代码被调用两次,请检查从何处调用它。您不必处理来自两个对象的两个不同对象的碰撞。将碰撞代码放在两个对象的“更智能”上,然后从那里开始。

标签: unity3d collision-detection collision


【解决方案1】:

您可以使用您的一个脚本(或相同的脚本)在另一个对象上执行 GetComponent,并将RecentCollisionObject 设置为当前脚本或游戏对象(可能还有一个给定的时间范围,只是为了增加安全性(如果只有一个触发它) ,但由于某种原因不是另一个))。

在每次碰撞时,您检查RecentCollisionObject 是否是另一个对象(如果不超过~0.01 秒)。如果为 true,则您知道 特定的碰撞必须已经被另一个对象刚刚处理过,因此重置该另一个对象的所有值并且不执行任何其他操作。因此,下一次发生的碰撞,无论多快,都将重新执行此循环并按预期工作。

这样你只让第一个触发碰撞的代码执行你的代码(就像一个声音)。关键是两个碰撞事件是在同一帧中运行的,所以无论哪个触发器先触发,都可以阻止第二个触发。

【讨论】:

  • 我喜欢你关于对象的想法,但我认为依靠 0.01 秒是没有意义的。为什么正好是 0.01?它应该可以在没有任何时间的情况下工作。
  • 在两个碰撞对象中只有一个触发其碰撞事件的情况下,这只是一种安全机制。我不确定这种情况是否存在,但如果确实存在,那么有必要这样做 - 否则你在随后的碰撞中会出现奇怪的行为。当然,您也可以采用下一个更新时间范围,而不是 0.01 秒。
【解决方案2】:

您可以使用 Unity 标记系统,在与特定标记对象碰撞时标记动作。

例如:

internal void OnTriggerEnter(Collider other)    {

        if (other.gameObject.tag == "Oject Tag") {
            this.GetComponent<AudioSource> ().PlayOneShot (objectTagSoundClip);
        }

只需要放置在游戏对象中的音频即可播放。

【讨论】:

  • 在我的例子中,每个对象都应该在撞击时播放音频。
【解决方案3】:

也许你有 2 个碰撞器。如果是这样,您可以检查 boxcollider 是否仅发生碰撞。你也可以试试碰撞假。希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 2012-09-14
    • 1970-01-01
    • 2022-11-04
    • 1970-01-01
    相关资源
    最近更新 更多