Jump to content
Unity Insider Forum

Ihandler Event in anderen Klasse benutzen.


TheOnlyOne

Recommended Posts

Guten Abend,

ich habe eine Klasse, welche das Ihandler Interface's verwendet. Nun möchte ich, dass in einer anderen Klasse, sobald OnDrag() Ereignis aktiv ist, ebenfalls paar Funktionen durchlaufen. Ich kann natürlich ein Bool verwenden, wenn OnDrag aktiv ist und in anderen Klasse über bool Funktionen starten, aber gibt bestimmt eine elegantere Lösung?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo,

Das lässt sich über C#-Events oder UnityEvents lösen. Mit C# funktioniert es etwa so:

public event System.Action<PointerEventData> Drag;

public void OnDrag(PointerEventData eventData)
{
  System.Action<PointerEventData> handler = Drag;
  if (handler != null)
  {
    handler(eventData);
  }
}

In der Klasse die darauf reagieren soll muss dann aber ein Event-Handler registriert und allenfalls wieder entfernt werden:

void OnEnable()
{
  otherObject.Drag += Other_Drag;
}

void OnDisable()
{
  otherObject.Drag -= Other_Drag;
}

private void Other_Drag(PointerEventData eventData)
{
  // Dieser Code wird dann ausgeführt, wenn bei der anderen Klasse das OnDrag ausgeführt wird.
}

Mit UnityEvents sähe es so aus:

public class MyDragEvent : UnityEvent<PointerEventData> {}

public MyDragEvent dragEvent;

void Start()
{
  if (dragEvent == null)
    dragEvent = new MyDragEvent();
}

public void OnDrag(PointerEventData eventData)
{
  dragEvent.Invoke(eventData);
}

Der Vorteil von UnityEvents ist, dass via Inspektor Objekte und Methoden zugewiesen werden können, die dann aufgerufen werden beim OnDrag. Aber natürlich können die Handler auch wie bei C# mit Code hinzugefügt werden:

void OnEnable()
{
  otherObject.dragEvent.AddListener(Other_Drag);
}

void OnDisable()
{
  otherObject.dragEvent.RemoveListener(Other_Drag);
}

void Other_Drag(PointerEventData eventData)
{
    // Dieser Code wird dann ausgeführt, wenn bei der anderen Klasse das OnDrag ausgeführt wird.
}

Oder meintest du Drag&Drop eines UI-Elements auf ein 3D-Objekt etc.? Dann müsste bei der Kamera einfach ein PhysicsRaycaster hinzugefügt werden, damit das Interface IDropHandler auch bei 3D-Objekten funktioniert.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielen Dank! Das ist genau wonach ich gesucht habe. Ich verstehe nicht ganz die deklaration und definition von Events in diesem Fall.

public event System.Action<PointerEventData> Drag;

Warum event klein geschrieben und was bedeutet System.Action<PointerEventData>?

 System.Action<PointerEventData> handler = Drag;
  

und diese Zeile verstehe ich auch nicht, kann man ohne diese Zeile direkt Drag(eventData) schreiben?

Wäre sehr dankbar wenn du mir das erklären könntest.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Event ist kleingeschrieben, weil das ein Sprachfeature von C# ist und somit ein Schlüsselwort. Also für C# hat das eine spezielle Bedeutung. Es weiss dann dass man ein Event definieren möchte.

Ein Event ruft, wenn es ausgelöst wird eine bestimmte Funktion auf. Beim definieren eines Events muss man auch definieren wie die Funktion genau aussehen soll, die dann aufgerufen wird. System.Action<PointerEventData> bedeutet: Eine Funktion ohne Rückgabewert (Action), mit genau einem Parameter vom Typ PointerEventData.

Um das Event auszulösen, benutzt man normalerweise den Code den ich in OnDrag() eingefügt habe. Im Prinzip könnte man auch direkt schreiben:

if (Drag != null)
{
  Drag(eventData); // <- löst das Drag-Event aus und übergibt das benötigte PointerEventData-Objekt
}

Die Zeile vor dem If ist nur eine lokale Variable namens handler und das Drag wird dieser handler-Variable zugewiesen. Danach wird das Event über die Variable ausgelöst. Das macht man in der Regel aus Gründen der Threadsicherheit, aber das ist erstmal nicht so wichtig.

In deinem Fall musst du das Event nicht selber auslösen, da das OnDrag bereits durch Unity über das Interface aufgerufen wird.

Ein Event kann dann mehrere Objekte haben die auf das Ereignis reagieren möchten. Beim Auslösen des Events werden automatisch alle Objekte benachrichtigt, die sich zuvor bei dem Event registriert haben. Das Objekt das darauf reagieren will, teilt dem Event sozusagen mit, welche Funktion vom Event aufgerufen werden soll, sobald es ausgelöst wird:

// Das Event soll bei Auslösung MeineFunktion aufrufen
// Ausgelöst wird das Event von der Quelle, dann wenn sie es für nötig hält bzw. in deinem Fall in OnDrag
quelle.Event += MeineFunktion;

private void MeineFunktion(PointerEventData eventData)
{
  // Und MeineFunktion muss genau so aussehen, wie das Event es verlangt
  // bzw. wie das Event definiert wurde. In diesem Fall System.Action<PointerEventData>
  // was void Name(PointerEventData parameterName) entspricht.
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Was es noch gibt sind die Methoden SendMessage und BroadcastMessage. Damit kannst du Methoden bei anderen MonoBehaviours ausführen lassen, allerdings läuft das über Reflection und kann je nachdem langsamer sein.

public void OnDrag(PointerEventData eventData)
{
  // Ruft die Methode bei allen MonoBehaviours auf dem selben GameObject auf (falls vorhanden)
  SendMessage("MyOnDrag", eventData, SendMessageOptions.DontRequireReceiver);
  // Ruft die Methode bei allen MonoBehaviours auf dem selben und untergeordneten GameObject auf (falls vorhanden)
  BroadcastMessage("MyOnDrag", eventData, SendMessageOptions.DontRequireReceiver);
  // Ruft die Methode bei allen MonoBehaviours auf dem selben und auf übergeordneten GameObjects auf (falls vorhanden)
  SendMessageUpwards("MyOnDrag", eventData, SendMessageOptions.DontRequireReceiver);
}

Aber es stellt sich die Frage, ob das ein Script ist, welches diese Events generell weiterleiten soll oder ob die Objekte an die du weiterleiten möchtest sowieso bekannt sind. Dann ginge es auch viel einfacher:

public AnderesScript anderesScript; // Via Inspektor ein Objekt/Behaviour zuweisen

public void OnDrag(PointerEventData eventData)
{
  anderesScript.Methode();
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...