2016-12-22 2 views
1

Ich habe ein Objekt, das sich in Richtung eines anderen Objekts bewegt und physisch mit ihm kollidiert. Ich möchte, dass dieses Kollisions-/Kollisions-Ereignis nur einmal auftritt. Ich habe versucht, eine bool zu verwenden, aber es hat nicht wie vorgesehen funktioniert. Es scheint, dass ich etwas falsch mache.Kollision erkennen/nur einmal kollidieren

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:

Ich möchte die „Schadenscode“ nur einmal laufen, auch wenn die zwei Objekte noch in Kontakt sind. Dieses Skript ist nur einem Objekt zugewiesen, nicht beiden.

+0

meinst du, dass die ganze Kollision nur einmal passieren sollte und beim zweiten Mal sollten sich diese Objekte wie ohne Collider verhalten oder du willst nur Schaden kontrollieren? –

+0

Ich möchte die ganze Kollision nur einmal passieren. – Abdou023

+0

Bereiten Sie verschiedene Ebenen für Ihr Spielobjekt vor. In den physikalischen Einstellungen deaktivieren Sie die Layer-Kollisionsmatrix für diese beiden Ebenen. Legen Sie für beide Objekte denselben Layer fest und ändern Sie den Layer für eines der Objekte nach der Kollision. Sie werden nicht mehr kollidieren. Sie können auch einen der Collider nach einer Kollision in einen Trigger umwandeln. –

Antwort

2

Ich weiß nicht, der einfachste Weg zu erklären, warum Ihr Code nicht funktioniert, aber ich werde es versuchen.

Sie haben zwei Gameobjects:

  1. Gameobject A mit doDamage variabel.

  2. GameObject B mit doDamage Variable.

Wenn Gameobject A kollidiert mit Gameobject B:

A .Die OnCollisionEnter2D Funktion Gameobject A genannt wird. if(other.gameObject.tag == "Target" && doDamage) wird ausgeführt, weil doDamage wahr ist.

B .Die doDamage Variable aus Gameobject A wird dann auf false eingestellt.

Die doDamage-Variable von GameObject B wird nicht beeinflusst.

Dann

C .Die OnCollisionEnter2D Funktion wird aufgerufen, auf Gameobject B. if(other.gameObject.tag == "Target" && doDamage) wird ausgeführt, weil doDamage wahr ist.

D .Der doDamage Variable von Gameobject B wird dann auf false eingestellt.

Ihr beider Schadenscode wird ausgeführt, weil doDamage in jedem OnCollisionEnter2D Aufruf immer wahr ist. Was Sie gerade tun, betrifft nur die doDamage Variable in jedem einzelnen Skript.

Was Sie derzeit tun:

Einstellung doDamage im local/dieses Skript false während auch wenn local/diese Überprüfung doDamage wird oder nicht.

Was brauchen Sie zu tun:

Set doDamage im anderen Skript false aber lesen Sie die local/diesedoDamage zu überprüfen, ob es gesetzt ist oder nicht.

Dies ist, wie es aussehen soll:

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

Es tut mir leid, dass ich das vorher nicht erwähnt habe, aber dieses Skript ist nur einem Spielobjekt zugewiesen, nicht beiden. – Abdou023

+0

Was meinst du damit, es einmal zu erkennen? – Programmer

+0

Wenn das erste Objekt das zweite Objekt trifft, bleibt die Kollision aktiv und das erste Objekt verursacht weiterhin Schaden. Ich möchte, dass der Schadenscode im Kollisionsereignis nur einmal ausgeführt wird. – Abdou023

0

Wenn Sie einmal einen Code-Snippet laufen, den Code direkt in dem Callback-Ereignisse ausführen, die Sie Ihren Code auslösen sollen.

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

Dies sollte nur einmal bei einer Kollision ausgelöst werden.

Wenn Sie wollen, dass diese immer nur passieren, wenn (zB wenn das Objekt das Skript halten waren etwas wieder treffen), werden Sie ein Flag muss sagen, dass der Schaden bereits geschehen ist:

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

Ich vermute, dass aufgrund des Codes, den du geteilt hast, beide Objekte in der Engine mehrfach kollidieren (sehr wahrscheinlich, wenn sie fest und physikgesteuert sind), was dazu führt, dass OnCollisionEnter mehrfach aufgerufen wird. OnCollisionEnter should only be called once per collision. Wenn Sie beobachten, dass es mehrmals aufgerufen wird, beobachten Sie tatsächlich mehrere Kollisionen oder Sie haben einen obskuren Unity-Bug gefunden. Der ehemalige ist viel, viel eher.

+0

Der erste Teil Ihres Codes unterscheidet sich nicht von dem, was ich gerade mache. – Abdou023