Jump to content
Unity Insider Forum

GameObjekt an GameObjekt


Gazinho

Recommended Posts

Guten Abend allerseits,

ich habe ein Programmierproblem, das ich mit meinen google-Fähigkeiten leider nicht lösen kann. Ich bin noch relativer Anfänger und finde leider keine (befriedigende) Lösung. Die Lösung mit GetComponent <> halte ich für eine äußerst unelegante Variante.

Es geht um folgendes (Beispielhaft im 2D ):

Ich möchte ein GameObjectP zu irgendeinem einem anderen von sehr vielen GameObjectX schicken. Ich markiere das GameObjectP mit OnMouseDown() {bool detected = true;} und möchte es dann mit Rechtsklick zum GameObjectX schicken: if (Input.GetMouseButtonDown(1) && /*Rechtsklick auf collider von GameObject2*/ ) {destination = GameObjectX.transform.position};  transform.Translate(destination etc.);.

Ich möchte letzten Endes nicht, dass GameObjectP von allen anderen GamObjectX über GetComponent abfrägt, ob es mit Rechtsklick angeklickt wurde. Gibt es eine charmantere Lösung?

Herzliche Grüße

Link zu diesem Kommentar
Auf anderen Seiten teilen

Moinsen!

Du hast ja einen Spieler und ein angeklicktes Objekt. Beide sind genau spezifiziert (weil du sie angeklickt hast), ein Durchgehen von mehreren Objekten ist also nicht nötig.

Die einfachste Lösung ist vermutlich, die Referenz auf dein GameObjectP in eine statische Variable zu schmeißen:

public class Mover : MonoBehaviour
{
  public static Mover selectedObject; // Quasi dein GameObjectP

  private void OnMouseDown()
  {
    selectedObject = this;
  }
  
  public void MoveTo(Vector3 position)
  {
    // ...
  }
}

...und dann das angeklickte GameObjectX Bescheid sagen lassen, dass der dort referenzierte Mover sich bitte zu sich bewegen soll:

public class Tile : MonoBehaviour
{
  private void OnMouseDown()
  {
    if (Mover.selectedObject)
    {
      Mover.selectedObject.MoveTo(transform.position);
    }
  }
}

Hab jetzt mal bei beiden OnMouseDown benutzt, kannst du beliebig abändern oder erweitern.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 weeks later...
Am 1.10.2020 um 21:06 schrieb Gazinho:

Herzlichen Dank! Ich schaue mir das gleich mal an 🙂

 

 

Am 30.9.2020 um 22:39 schrieb Sascha:

Moinsen!

Du hast ja einen Spieler und ein angeklicktes Objekt. Beide sind genau spezifiziert (weil du sie angeklickt hast), ein Durchgehen von mehreren Objekten ist also nicht nötig.

Die einfachste Lösung ist vermutlich, die Referenz auf dein GameObjectP in eine statische Variable zu schmeißen:


public class Mover : MonoBehaviour
{
  public static Mover selectedObject; // Quasi dein GameObjectP

  private void OnMouseDown()
  {
    selectedObject = this;
  }
  
  public void MoveTo(Vector3 position)
  {
    // ...
  }
}

...und dann das angeklickte GameObjectX Bescheid sagen lassen, dass der dort referenzierte Mover sich bitte zu sich bewegen soll:


public class Tile : MonoBehaviour
{
  private void OnMouseDown()
  {
    if (Mover.selectedObject)
    {
      Mover.selectedObject.MoveTo(transform.position);
    }
  }
}

Hab jetzt mal bei beiden OnMouseDown benutzt, kannst du beliebig abändern oder erweitern.

Funktioniert übrigens traumhaft! Ich hatte diese Idee mit der static-Variablen zwar schonmal, damals hatte das aber nicht funktioniert. Wahrscheinlich habe ich damals irgendetwas übersehen (vielleicht diese zusätzlich public zu deklarieren).

Mit dem public-static-Zugriffsmodifikator lässt sich also auch in Unity hervorragend zwischen den Skripten der Objekte "kommunizieren". Wenn man das googlet, dann bekommt mal leider nur die zu komplizierten, aber auch funktionierenden Varianten mit GetComponent oder RayCast. 

Herzlichen Dank für die schnelle und treffende Antwort! Hat sich absolut gelohnt, sich hier anzumelden!

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 1 Stunde schrieb Gazinho:


Mit dem public-static-Zugriffsmodifikator lässt sich also auch in Unity hervorragend zwischen den Skripten der Objekte "kommunizieren". Wenn man das googlet, dann bekommt mal leider nur die zu komplizierten, aber auch funktionierenden Varianten mit GetComponent oder RayCast. 

Oh, falle da nicht auf dieselbe Sache rein wie so viele vor dir: Static bedeutet, dass davon immer nur eines existieren kann. Wenn du also z.B. eine Tür hast und einen Schalter, der die Tür öffnet - Klar geht das irgendwie mit static. Aber sobald du eine zweite Tür hast funktioniert das überhaupt nicht mehr. Static ist kein nettes Mittel, um so etwas wie Kommunikation zwischen Klassen zu erreichen. Es macht eben diese eine Sache, dass eine Ding nur einmal existiert und nicht einmal pro Objekt. Das kann sinnvoll sein oder auch nicht, je nach Situation.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Möglicherweise habe ich mich unklar ausgedrückt. Ich meinte den Ansatz, wenn es darum geht, einer Klasse eine Information zu geben. Auch in der objektorientierten Programmierung scheint es ja auch so zu sein, dass es immer eine "führende" Klasse gibt, die alle Ausführungen verwaltet. Es macht ja wenig Sinn, wenn die einzelnen Objekte unverbindlich nebeneinander her existieren. Der "führenden" Klasse müssen von den anderen Objekten Informationen übergeben werden - es macht in meinen Augen wenig Sinn, wenn sich die führende Klasse die Informationen einholt.

Ich bin echt noch recht frisch in der Programmierung, ich habe erst im Dezember 2019 mich wieder mit der Thematik Programmierung beschäftigt. Ich konnte vor 30 Jahren passabel BASIC auf dem C64 und nachfolgend ein bisschen Turbo-Pascal auf dem PC. Danach war ich quasi 30 Jahre raus. Aber wenn man der objektorientierten Programmierung (nach meinem rudimentären Verständnis) folgt, ist das "Main-Objekt" immer der User vor dem Bildschirm. Da müssen die Informationen hin.

Innerhalb der Unity werden die Informationen der einzelnen Objekte aber auch in einer führenden Klasse gesammelt, damit sie in Relation zueinander stehen können. Dafür dienst nach vorläufiger Bewertung die static-Variante vorzüglich. Ich lasse mich aber gerne jederzeit eines besseren belehren, denn ich habe mit meiner Ursprungsfrage ja nicht nach einer funktionierenden Lösung gefragt, sondern nach der logischsten.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Am 11.10.2020 um 00:35 schrieb Gazinho:

Auch in der objektorientierten Programmierung scheint es ja auch so zu sein, dass es immer eine "führende" Klasse gibt, die alle Ausführungen verwaltet.

Absolut überhaupt nicht. Ganz im Gegenteil.

Gerade in Unity kann man sehr gut sehen, dass es sich lohnt, dass Objekte sich so weit wie möglich um ihre eigenen Angelegenheiten kümmern. Nehmen wir das Standardbeispiel mit dem Knopf, der eine Tür öffnet. Da hat man ein Knopf-Objekt und ein Tür-Objekt. Da "welche Tür öffnet dieser Knopf" Teil des Leveldesigns ist, ist es sinnvoll, den Code so zu schreiben, dass man diese Frage im Editor durch Reinziehen beantwortet. Man baut also ein Feld in das Button-Script, wo man die gewünschte Tür reinziehen kann. Viele Anfänger (und leider auf Fortgeschrittene...) schwören ja auf Manager-Klassen. Da haste dann in dem Fall irgendwie nen Tür-Manager und der Button benutzt den irgendwie, aber warum?

Ich kann dir versprechen: Man braucht diese zentralen Manager-Dinger niemals. Und es gibt immer eine bessere Lösung. Also nicht nur eine gleich gute, sondern eine bessere. Versteh mich nicht falsch - klar gibt's oft zentralisierte Knotenpunkte. Hier zum Beispiel, da gibt's dieses Event, wo sich Objekte registrieren, und andere Objekte können es auslösen. Das ist da sinnvoll, weil in diesem Fall die Dinge, die auf das Game Over-Event reagieren und die, die es auslösen, sich nicht kennen sollten. Dinge, die ihre Position zurücksetzen und Trigger, in die der Spieler nicht hineinfliegen soll, haben halt keine inhärente semantische Verbindung. Aber dieses Event oder die Klasse, in der es steckt, sind nicht "führend". Es hängt da so rum und kann von anderen Objekten benutzt werden. Von sich aus macht das Ding gar nichts.

Allgemein gilt: Je weniger Abhängigkeiten du hast, desto besser. "Keine" ist Quatsch, der Knopf muss ja die Tür kennen. Aber vermeide eben unnötige Abhängigkeiten, und halte damit die Anzahl so gering wie möglich. Eine zentral führende Klasse ist da das genaue Gegenteil.

Am 11.10.2020 um 00:35 schrieb Gazinho:

Innerhalb der Unity werden die Informationen der einzelnen Objekte aber auch in einer führenden Klasse gesammelt, damit sie in Relation zueinander stehen können.

Unity hat halt Dependency Injection, aber das ist ein System, das im Hintergrund funktioniert und da nicht so richtig als Beispiel funktioniert. Und ja, du hast in objektorienterten Sprachen, wie überall anders auch, irgendwo deinen Programmeinstiegspunkt. Aber davon löst man sich halt so schnell wie möglich los. Und in Unity bist du eben in der Situation, dass du im Editor Dinge zusammenbaust und problemlos so tun kannst, als gäbe es den ganzen Code im Hintergrund nicht, der da die Szene lädt und die Referenzen so zusammenbaut, wie du es im Editor durch Reinziehen definiert hast.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...