Jump to content
Unity Insider Forum

Scriptkommunikation - ist es Möglich einen Platzhalter zu deklarieren?


malzbie

Recommended Posts

Hi!

Folgendes Problem:

Ich baue mehrere Flipper und greife von Scripts meiner Objekte auf andere Scripts zu um z.B. Punkte zu übermitteln oder den Spielstatus abzufragen.

Jetzt habe ich 5 zentrale Scripte auf der Camea, die Berechnen, die Spiellogik auswerten und Flags setzen, Animieren und Beleuchten und Anzeigen.

Diese 5 Scripts kommunizieren untereinander und mit den Komponenten auf dem Tisch.

 

Da jetzt alleine mein Berechnungsscript schon 800 Zeilen hat und davon die Hälfte spezifisch für diesen Tisch sind, wollte ich gerne ein weiteres Berechnungsscript für den neuen Tisch erstellen.

Jede Tisch-Komponente, wie zum Beispiel der Bumper, ist mit dem Berechnungsscript verbunden und springt in für sie geschaffene Methoden rein.

So etwa:

 

berechnungsScript rechner;

void Start(){
  rechner = Camera.main.GetComponent<berechnungsScript>();
}
void OnCollisionEnter(Collision other) {
  rechner.Bumper();
  ...
}

 

Im Berechnungsscript gibt es dann diese Methode:

 

public void Bumper() { // von Bumper
  bumperhits++;
  int points = bumperValue;
  DoubleScore(points);
  bonus += bumperBon;
  jackpot += bumperJack;
}

 

Beim neuen Flipper wird es diese Methode auch geben, aber es werden auch ganz viele themenspezifische Berechnungen da sein. Lässt sich schlecht teilen.

Also wollte ich ganz einfach die Variable "rechner" als eine Art Platzhalter deklarieren und dann je nach Tisch ein anderes Script damit verbinden.

 

Ich glaube aber inzwischen, dass das nicht geht.

Ich habe es schon mit Component und MonoBehaviour probiert, was nicht geht. Das Schlüsselwort Var lässt sich nur im Code selber nutzen, was für mich nicht funktioniert.

Andere Möglichkeiten fallen mir jetzt nicht ein.

 

Habt ihr da einen Tipp für mich?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Kannst du nicht einfach eine abstrake Oberklasse machen und für jeden neuen Tisch erbst du einmal von dieser Oberklasse?

Die Oberklasse hat dann halt zb. die Funktion Bumper()

 

Sollte das mit GetComponent() nicht machbar sein kannst du die ja auch so designen das die Oberklasse sowas hier hat:

 

public class Oberklasse : MonoBehaviour
{
public static Oberklasse Instance;
}
public class Tisch1 : Oberklasse
{
public void Awake()
{
Instance = this;
}
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Am besten ist es immer, wenn man so etwas mit Variablen lösen kann.

Sobald sich aber strukturell etwas ändert, ist eine kleine Vererbungshierarchie bestimmt nicht schlecht; dann sieht das etwa so aus, wie Djeurissen sagt.

Muss aber nicht statisch sein.

Wenn du das hier hast:

public abstract class Berechner : MonoBehaviour
{
 public abstract void Bumper();
}

public class BerechnerTisch1 : Berechner
{
 public override void Bumper()
 {
   // Code
 }
}

dann kannst du den BerechnerTisch1 auf die Kamera setzen und ihn trotzdem mit

GetComponent<Berechner>()

finden.

 

Wenn du es nicht schön finden solltest, x erbt von y erbt von MonoBehaviour zu haben (ist ein bisschen eklig wegen der Unity-Methoden, Awake, Start usw.), dann ginge auch, dass Berechner von ScriptableObject oder von (System.)object erbt.

Bei letzterem denke ich z.B. an ein Dictionary<BerechnerTyp, T> where T : Berechner, wobei BerechnerTyp ein enum wäre.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Jo. Danke euch zweien. Da kann ich morgen mal mit rum spielen.

Aber ich bin mir nicht sicher ob die Vorschläge alles abdecken. Denn ich springe ja nicht nur in Methoden rein sondern frage auch Variablen ab.

Na ja, ich könnte natürlich auch Variablen mit override überschreiben... hmm... es sieht so aus als wäre der Aufwand recht hoch.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Klingt nach einem guten Anwendungsfall für ein Interface.

Die verschiedenen Berechnungsklassen bekommen alle ein gemeinsames Interface verpasst (sind eigentlich dann die Basismethoden die alle Klassen auf jeden Fall besitzen). An der Stelle wo das Berechnungsskript dann benötigt, holst du dir dann nur das Interface und nicht die konkrete Klasse. GetComponent<>() sollte auch mit einem Interface funktionieren. Die Verwendung eines Interfaces macht vor allem dann Sinn, wenn die verschiedenen Berechnungsklassen außer den Schnittstellenmethoden sonst nichts miteinander gemeinsam haben, also intern auf unterschiedliche Datenstrukturen zugreifen oder gar eine eigene Vererbungsstruktur haben.

 

Über eine abstrakte Oberklasse wird es wohl auch gehen oder ist sinnvoll, wenn die verschiedenen Klassen gemeinsame Daten teilen und die Methoden gemeinsame Abschnitte besitzen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Interfaces sind in Unity ziemlich gruselig. Zumindest zusammen mit MonoBehaviours.

var mb = gameObject.AddComponent<MonoBehaviourWithInterface>();
var mbi = (TheInterface)mb;
DestroyImmediate(mb);
if(mbi != null)
{
 print("Au weia");
}

 

Na ja, ich könnte natürlich auch Variablen mit override überschreiben...

Wenn der Wert eines Feldes statisch für jede Klasse ist, dann bauchst du sie gar nicht erst vererben.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich löse das jetzt mit der abstrakten Klasse und deklariere dort dann auch alle Variablen, die ich von außen abfrage.

Das ist ganz ok, denn ich habe nur wenige spezifische Variablen.


public abstract class berechnungsScript : MonoBehaviour {

// allgemeine Variablen
public int multiplikator=1; // der Multiplikator, von UIMessage und UIScript abgefragt
public int minHighscore; // der zu überbietende Highscore
public int bonus; // UIScript braucht das für Anzeige
public int bumperhits = 0;
public bool zeigeBumperInfo;
public int score = 0;
public int extraballscore = 0;
public bool doublescore = false;

//TTFB Variablen
public bool rampLRlitEB;
public bool rampRLlitEB;
public int rampLRmulti = 1;
public int rampRLmulti = 1;

// allgemeine Methoden
public abstract void HoleTargetOff();  // von Hole
public abstract void HoleTargetOn(); // von Hole
public abstract void AddHoleValue(int value); // kommt von UIMessage
public abstract void AddHoleMultiplikator(); // kommt von UIMessage
public abstract void AddDoubleBonus(); // kommt von UIMessage
public abstract void BonusHeld(); // kommt von UIMessage
public abstract void Slingshot();
public abstract void MultiLane(bool on);
public abstract void Bulltargets(bool on);
public abstract void Droptargets();
public abstract void Lanetargets(bool on);
public abstract void Bumper();

// TTFB Methoden
public abstract void SpyEnabledPoints();
public abstract void SpyDonePoints();
public abstract void EnemyEnablePoints();
public abstract void EnemyDonePoints();
public abstract void BaseEnablePoints();
public abstract void BaseDonePoints();
public abstract void FinalDonePoints();
public abstract void FinalTargetPoints();


}

 

Es ist jetzt zwar doch einigermaßen aufwendig, aber ich kann dann auch gleich mal meine Scripte ordnen. :)

 

Danke für eure Inputs! :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...