Unity 3D:如何正确检测碰撞是否已被另一个碰撞参与者处理?

3
我有一个名为CollisionHandler的类,其中包含OnCollisionEnter方法。游戏中的每个可碰撞实体都将CollisionHandler作为组件。因此,当两个对象碰撞时,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的新手)它是否是最佳实践,如果是,请提出其他可能的解决方案。
请注意,我没有问“为什么OnCollisionEnter会被调用两次?”("Why is OnCollisionEnter getting called twice?")。我知道为什么会发生这种情况。我的问题与此不同,尽管它提到了相同函数的名称,但它仍然没有问相同的问题。

1
我在脑海中想出的所有解决方案都包括一些标志或值,我会读取并比较它们,以便知道其他人已经处理了这个冲突。而不是存储当前时间/帧数,这听起来更合乎逻辑!所以我想说,如果这已经起作用了,那就是一个好的解决方案 ;) - derHugo
如果您的代码被调用两次,请检查它是从哪里被调用的。您不应该处理来自两个不同对象的碰撞。将碰撞代码放在这两个对象中“更聪明”的对象上,然后从那里开始。 - Eliasar
可能是重复的问题,与为什么OnCollisionEnter会被调用两次?相似。 - Eliasar
3个回答

0

你可以在另一个对象上使用GetComponent和你的脚本(或相同的脚本),将RecentCollisionObject设置为当前脚本或gameObject(也许只是为了额外的安全性,给定一个时间范围(如果只有一个触发它,但由于某种原因另一个没有触发))。

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

通过这种方式,您只允许第一个触发碰撞代码执行您的代码(例如声音)。关键是两个碰撞事件在同一帧中运行,因此无论哪个先触发,您都可以防止第二个运行。


我喜欢你的对象想法,但我认为依赖0.01秒没有意义。为什么是0.01秒?它应该可以在没有任何时间限制的情况下正常工作。 - Serg
这只是一种安全机制,以防仅有2个碰撞对象之一触发其碰撞事件。我不确定是否存在这种情况,但如果存在,拥有它是必要的-否则在后续碰撞中会出现奇怪的行为。当然,您也可以采取下一个Update时间框架,而不是0.01秒。 - Battle

0
也许你有两个碰撞器。如果是这样,你可以检查是否只有boxcollider发生了碰撞。你也可以尝试在离开碰撞时进行操作。希望能帮到你。

0

你可以使用Unity标签系统,将标签附加到特定对象上以触发动作。

例如:

internal void OnTriggerEnter(Collider other)    {

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

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


在我的情况下,每个物体都应该在碰撞时播放音频。 - Serg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接