Unity 3D:检测已经为另一个碰撞参与者处理碰撞的正确方法是什么?
Unity 3D: what is the correct way to detect that the collision has already been processed for another collision participant?
我有一个 class CollisionHandler
,它有 OnCollisionEnter
方法。游戏中的每个 可碰撞 实体都有 CollisionHandler
作为组件。因此,当 2 个对象发生碰撞时,OnCollisionEnter
方法被调用 两次 并且没关系,因为损坏和其他事情是由于对象 "B" 接触对象而处理的"A" 反之亦然。
此外,每次碰撞都会产生闪光效果并播放撞击声,当然,这些效果也会在每次碰撞时播放两次。尽管它不会被玩家察觉到,但无论如何它似乎都不正确。为了防止它,我想出了以下解决方案:我将当前帧号保存在另一个碰撞参与者中,这样它就会知道这些效果已经被第一个参与者播放过。
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 的新手)这是最佳实践,如果是这样,请提出其他可能的解决方案。
请注意,我没有问 。我知道为什么会这样。我的问题是关于另一个的,虽然它确实提到了同一个函数的名称,但它仍然没有问同样的问题。
您可以使用您的一个脚本(或同一个脚本)在另一个对象上执行 GetComponent,并将 RecentCollisionObject 设置为当前脚本或游戏对象(可能还有一个给定的时间范围,只是为了额外的安全性(如果只有一个触发它,但由于某种原因没有触发另一个))。
在每次碰撞时,您检查 RecentCollisionObject 是否是另一个对象(并且是否过去了不超过 ~0.01 秒)。如果为真,则您知道 特定的碰撞一定已经被另一个对象处理过,所以重置那个对象的所有值并且什么都不做。因此,下一次发生的碰撞,无论多快,都会重新执行此循环并按预期工作。
这样你就只让第一个触发碰撞代码的人执行你的代码(比如声音)。重点是两个碰撞事件都在同一帧运行,所以不管哪个先触发,你都可以防止第二个运行.
您可以使用 Unity 标签系统,您可以标记与特定标记对象发生碰撞时发生的动作。
例如:
internal void OnTriggerEnter(Collider other) {
if (other.gameObject.tag == "Oject Tag") {
this.GetComponent<AudioSource> ().PlayOneShot (objectTagSoundClip);
}
只需要在游戏对象中放置一个音频即可播放。
也许你有 2 个 Colliders。如果是这样,您可以检查例如 boxcollider 是否仅发生碰撞。您也可以尝试休假。希望对你有帮助。
我有一个 class CollisionHandler
,它有 OnCollisionEnter
方法。游戏中的每个 可碰撞 实体都有 CollisionHandler
作为组件。因此,当 2 个对象发生碰撞时,OnCollisionEnter
方法被调用 两次 并且没关系,因为损坏和其他事情是由于对象 "B" 接触对象而处理的"A" 反之亦然。
此外,每次碰撞都会产生闪光效果并播放撞击声,当然,这些效果也会在每次碰撞时播放两次。尽管它不会被玩家察觉到,但无论如何它似乎都不正确。为了防止它,我想出了以下解决方案:我将当前帧号保存在另一个碰撞参与者中,这样它就会知道这些效果已经被第一个参与者播放过。
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 的新手)这是最佳实践,如果是这样,请提出其他可能的解决方案。
请注意,我没有问
您可以使用您的一个脚本(或同一个脚本)在另一个对象上执行 GetComponent,并将 RecentCollisionObject 设置为当前脚本或游戏对象(可能还有一个给定的时间范围,只是为了额外的安全性(如果只有一个触发它,但由于某种原因没有触发另一个))。
在每次碰撞时,您检查 RecentCollisionObject 是否是另一个对象(并且是否过去了不超过 ~0.01 秒)。如果为真,则您知道 特定的碰撞一定已经被另一个对象处理过,所以重置那个对象的所有值并且什么都不做。因此,下一次发生的碰撞,无论多快,都会重新执行此循环并按预期工作。
这样你就只让第一个触发碰撞代码的人执行你的代码(比如声音)。重点是两个碰撞事件都在同一帧运行,所以不管哪个先触发,你都可以防止第二个运行.
您可以使用 Unity 标签系统,您可以标记与特定标记对象发生碰撞时发生的动作。
例如:
internal void OnTriggerEnter(Collider other) {
if (other.gameObject.tag == "Oject Tag") {
this.GetComponent<AudioSource> ().PlayOneShot (objectTagSoundClip);
}
只需要在游戏对象中放置一个音频即可播放。
也许你有 2 个 Colliders。如果是这样,您可以检查例如 boxcollider 是否仅发生碰撞。您也可以尝试休假。希望对你有帮助。