仅检测碰撞/碰撞一次

时间:2016-12-22 19:39:21

标签: c# unity3d collision-detection

我有一个物体向另一个物体移动并与物体碰撞,我希望碰撞/碰撞事件只发生一次。我尝试使用bool,但它并没有按预期工作。我似乎做错了。

bool doDamage = true;
void OnCollisionEnter2D(Collision2D other)
{
    if (other.gameObject.tag == "Target" && doDamage)
    {
        doDamage = false;
        // damage code
    }
}

void OnCollisionExit2D(Collision2D other)
{
    if (other.gameObject.tag == "Target")
    {
        doDamage = true;
    }
}

编辑:

我想要"损坏代码"即使两个物体仍然接触,也只运行一次。此脚本仅分配给1个对象,而不是两个。

2 个答案:

答案 0 :(得分:2)

我不知道最简单的方法来解释为什么你的代码无效但我会尝试。

你有两个游戏对象:

  1. 带有doDamage变量的GameObject A

  2. 带有doDamage变量的
  3. GameObject B

  4. GameObject A GameObject B 发生冲突时

    A 。在 GameObject A 上调用OnCollisionEnter2D函数。 if(other.gameObject.tag == "Target" && doDamage)执行是因为doDamage为真。

    B 。然后将来自 GameObject A doDamage变量设置为false

    这不会影响来自 GameObject B doDamage变量。

    然后

    C 。在 GameObject B 上调用OnCollisionEnter2D函数。 if(other.gameObject.tag == "Target" && doDamage)执行是因为doDamage为真。

    D 。然后将来自 GameObject B doDamage变量设置为false

    您的损坏代码都会运行,因为在doDamage次调用中OnCollisionEnter2D始终为true。您目前正在做的只是影响每个个人脚本中的doDamage变量。

    您目前正在做什么

    本地/此脚本中的doDamage设置为false,同时还要检查是否设置了 local / this doDamage或不

    您需要做什么

    其他脚本中的doDamage设置为false,但请阅读 local / this doDamage以检查是否已设置或不。

    这应该是这样的:

    public class DamageStatus : MonoBehaviour
    {
        bool detectedBefore = false;
    
        void OnCollisionEnter2D(Collision2D other)
        {
            if (other.gameObject.CompareTag("Target"))
            {
                //Exit if we have already done some damage
                if (detectedBefore)
                {
                    return;
                }
    
                //Set the other detectedBefore variable to true
                DamageStatus dmStat = other.gameObject.GetComponent<DamageStatus>();
                if (dmStat)
                {
                    dmStat.detectedBefore = true;
                }
    
                // Put damage/or code to run once below
    
            }
        }
    
        void OnCollisionExit2D(Collision2D other)
        {
            if (other.gameObject.tag == "Target")
            {
                //Reset on exit?
                detectedBefore = false;
            }
        }
    }
    

答案 1 :(得分:0)

如果要运行一段代码,请直接在要触发代码的回调事件中运行代码。

void OnCollisionEnter2D(Collision2D other)
{
    DoSomeDamageTo(other.gameObject);
}

这应该只在碰撞时触发一次。

如果您希望这只发生一次(例如,如果持有该脚本的对象再次击中某个东西),您需要一个标记来说明损坏已经完成:

bool hasHitSomething = false;
void OnCollisionEnter2D(Collision2D other)
{
    if (!hasHitSomething)
    {
        DoSomeDamageTo(other.gameObject);
        hasHitSomething = true;
    }
}

我怀疑给出了你共享的代码,要么对象在引擎中多次碰撞(如果它们是实体和物理控制的话,很可能),导致OnCollisionEnter被调用多次。 OnCollisionEnter should only be called once per collision.如果您正在观察它被多次调用,您实际上是在观察多次碰撞,或者您发现了一个模糊的Unity错误。前者很多,很多更有可能。