Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

1

03.05.2017, 10:07

Interfaces in Unity nutzen / Methoden von unbekannten erbenden Klassen aufrufen

Hi,
ich habe 4 verschiedene "Zellen". Einfach Würfel mit jeweils 1 Script. Da die Methoden der Scripte aber alle gleich sind, erben diese 4 von einer Zellbasis und implementieren ein Interface.

Zu Beginn werden 100 Zellen erzeugt, zufällig zwischen diesen 4 Zellen ausgewählt und in einer Liste gespeichert. Da jede Zelle durch das Interface die Methoden implementiert, kann ich diese ja bei einer Schleife aufrufen. Aber wie lasse ich dynamisch das Script des GameObjects suchen?

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public abstract class CommonCell : Monobehaviour
{
// ist aktuell noch leer
}

public Interface ICell
{
    void Methode1();
    void Methode2();
}

public class Zelle1 : CommonCell, ICell
{
   public void Methode1()
{
// Tue dies
}

public void Methode2()
{
// Tue jenes
}
}

public class Zelle2 : CommonCell, ICell
{
   public void Methode1()
{
// Tue dies
}

public void Methode2()
{
// Tue jenes
}
}


Und die Liste liegt in einem Store. In diesem erfolgt dann auch der Aufruf mit einer Schleife

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Store
{
    private List<GameObject> cells = new List<GameObject>(); // Wird gefüllt

    private void ActivateCells()
{
     foreach(GameObject c in cells)
{
     c.GetComponent<???>().Methode1();
     c.GetComponent<???>().Methode2();
}
}
}


Die Sauberkeit / Performanz der Schleife mal nicht beachten, es geht mir nur darum, eine Rückmeldung zu bekommen, ob ich meine Idee überhaupt so umsetzen kann und vielleicht sogar einen möglichen Lösungsweg zu bekommen.

Das GameObject "c" muss sein Script finden (Zelle1, Zelle2, Zelle3, Zelle4) und soll dann die Methode im Script aufrufen, sichergestellt durch das Interface.

Leider habe ich Interfaces erst frisch kennen gelernt, es kann also sein, dass meine Idee überhaupt nicht umsetzbar ist, klingt einleuchtend, weil wie sollte "c" an das passende Script gelangen, aber vielleicht kann ich die Liste auch überarbeiten, dass nicht nur die Zelle in der Liste (oder im Tuple / oder im Array / ...) liegt, sondern auch das zugehörige Script.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

03.05.2017, 10:24

Bin grad auf dem Sprung und habe den Text nur überflogen. Du kannst doch bei GetComponent die Klasse angeben die du zurück haben möchtest. Da gibst du deinen konkreten Klassen an, so wie du es bei allen anderen Komponenten auch machen würdest. In deinem Fall also:

Quellcode

1
2
c.GetComponent<Zelle1>();
// ...
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

3

03.05.2017, 10:30

aber genau da liegt ja meine Frage :D

ich suche einen Weg, "c" die richtige Klasse einfügen zu lassen. c ist ja erstmal allgemein, dahinter könnten sich alle 4 zellen verbergen. c muss ja seine Komponente selbst kennen.

Und genau da liegt ja auch meine Frage, ob ich da vielleicht Blödsinn erreichen will, bzw. meine Idee gar nicht umsetzbar ist, weil woher soll man über eine vorerst allgemeine Variable an das jeweilge Script gelangen.

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

4

03.05.2017, 10:35

Mir kam nur der Gedanke, in die Liste zu jedem Objekt noch einen zweiten Wert einzutragen, das Script.

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

5

03.05.2017, 15:04

Also ich habs jetzt mal ohne Interface gelöst

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public abstract class CommonCell : Monobehaviour
{
    public abstract void Methode1();
    
    public abstract void Methode2();
}





public class Zelle1 : CommonCell
{
   public override void Methode1()
{
// Tue dies
}

public override void Methode2()
{
// Tue jenes
}
}





public class Zelle2 : CommonCell
{
  public override void Methode1()
{
// Tue dies
}

public override void Methode2()
{
// Tue jenes
}
}





public class GameController
{
    private List< CommonCell > cells = new List< CommonCell >(); // Wird gefüllt

    private void Methode()
{
     foreach(CommonCell c in cells)
{
     c.Methode1();
     c.Methode2();
}
}
}

Renegade

Alter Hase

Beiträge: 494

Wohnort: Berlin

Beruf: Certified Unity Developer

  • Private Nachricht senden

6

03.05.2017, 19:52

1. Warum speicherst du nicht einfach eine Liste des Interfaces? Ich habe die Befürchtung das du möglicherweise MonoBehaviour "falsch" verwendest. Folgendes wäre vollkommen legitim:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class SpecialCell : ICell {
[...]
}

public class SomeClass {

   List<ICell> cells = new List<ICell>();

   void Foo() {
      cells.Add(new SpecialCell());
   }

   void Bar() {
      foreach(var cell in cells) {
         cell.Method1();
         cell.Method2();
      }
   }

}


2. ...oder möchtest du, dass die Schleife "erkennt" ob sie Method1 oder Method2 aufrufen muss, je nachdem wer sie implementiert?
3. Ansonsten wäre folgende generische Lösung auch denkbar:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
private T GetInterfacet<T>(GameObject gameObject) where T : class {
   return gameObject.GetComponent(typeof(T)) as T;
}

private void Foo() {
   foreach(var gameObject in list) {
      ICell cell = GetInterface<ICell>(gameObject);
      cell?.Method1();
      cell?.Method2();
   }
}
Liebe Grüße,
René

Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von »Renegade« (03.05.2017, 20:14)


Werbeanzeige