2016-12-22 9 views
1

У меня есть объект, который перемещается к другому объекту и физически сталкивается с ним, я хочу, чтобы событие столкновения/столкновения произошло только один раз. Я пробовал использовать 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; 
    } 
} 

Edit:

Я хочу «повреждения кода», чтобы запустить только один раз, даже если 2 объекты все еще находятся в контакте. Этот скрипт присваивается только одному объекту, а не тем и другим.

+0

Вы имеете в виду, что все столкновения должны происходить только один раз, и во второй раз эти объекты должны вести себя как без коллайдеров или вы просто хотите контролировать повреждение? –

+0

Я хочу, чтобы все столкновение произошло только один раз. – Abdou023

+0

Подготовьте различные уровни для игрового объекта. В физических настройках снимите отметку с матрицы столкновений слоев для этих двух слоев. Установите одинаковый слой для обоих объектов и измените слой для одного из них после столкновения. Они больше не будут сталкиваться. Также вы можете просто сменить один из коллайдеров на триггер после столкновения. –

ответ

2

Я не знаю, как проще всего объяснить, почему ваш код не работает, но я попробую.

У вас есть два GameObjects:

  1. GameObject A с doDamage переменной.

  2. GameObject B с doDamage переменная.

Когда GameObject A сталкивается с GameObject B:

OnCollisionEnter2D функция .The вызывается GameObject A. if(other.gameObject.tag == "Target" && doDamage) выполняет, потому что doDamage - это правда.

В .The doDamage переменной от GameObject A затем устанавливается на false.

Это не влияет на переменную doDamage от GameObject B.

Затем

С .The OnCollisionEnter2D функция вызывается GameObject B. if(other.gameObject.tag == "Target" && doDamage) выполняет, потому что doDamage - это правда.

D .The doDamage переменной от GameObject B затем устанавливается на false.

Оба кода повреждения будут работать, потому что doDamage всегда верно в каждом вызове OnCollisionEnter2D. То, что вы сейчас делаете, влияет только на переменную doDamage в каждом отдельное скрипт.

Что вы сейчас делаете:

Установка doDamage в локальной/этого сценария к false, а также проверки, если локальный/этотdoDamage установлен или нет.

Что вам нужно сделать:

Набор doDamage в сценарии другой к false но читать местный/это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; 
     } 
    } 
} 
+0

Простите, что я не указывал это раньше, но этот скрипт присваивается только одному игровому объекту, а не тем и другим. – Abdou023

+0

Тогда что вы имеете в виду, обнаружив его один раз? – Programmer

+0

Когда первый объект попал во второй объект, столкновение остается активным, и первый объект продолжает наносить урон. Я хочу, чтобы код повреждения в событии столкновения запускался только один раз. – Abdou023

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. Первый много, много более вероятно.

+0

Первая часть вашего кода не отличается от того, что я делаю. – Abdou023