Jump to content
Unity Insider Forum

Übergeordnete Klasse von GameObject


landvogt

Recommended Posts

Hi,

meine Klasse "Unit"  erbt nicht von Monobehaviour, enthält aber eine Variable  GameObject.

Ungefähr so :

public class Unit {

public GameObject VUnit;

}

Per Physics.Raycast usw.  wird erfolgreich das GameObject zurückgegeben, über das der Mauszeiger gerade fährt.

Wie komme ich nun vom jeweiligen GameObject "VUnit" auf dessen Klasse "Unit" ?

Mit "transform.parent" gehts nicht, weil ich dem GO "VUnit" nicht das parent "Unit" zuweisen kann, weil "Unit" selber nicht vom Typ GameObject ist ...

 

 

LG

 

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Gar nicht. Beliebig viele Objekte (nicht "Klassen") vom Typ "Unit" können dasselbe GameObject referenzieren. Es ist kein Rückschluss möglich, wer alles ein Objekt referenziert.

Was auch immer du mit diesem Konstrukt vorhast, lässt sich auf eine andere Art sicherlich besser (bzw. überhaupt erst) bewerkstelligen. Was hast du also eigentlich vor?

Link zu diesem Kommentar
Auf anderen Seiten teilen

HI Sascha,

 

naja, einfach von der "Grafik" (GO)  auf die Instanz der verwaltenden Klasse "Unit" rückschliessen, um dann u.a. Methoden wie "MoveUnit" etc.  in "Unit" durchführen zu können.

Das funktioniert auch  , wenn ich bei dem GameObject nach Erzeugung in "transform.parent.name" z.B. den Index aus dem UnitArray reinschreiben lasse.

Bei MausHit gibt der String "name" des GO den korrekten Index zurück. z.B. "U3" , "U7" o.ä..  , aus dem String mache ich dann ein int und hab den korrekten Index aus dem "UnitArray".

Damit sind dann MEthodenaufrufe aus "Unit" möglich, aber so ist das mit Sichherheit nicht gedacht .... , dachte halt, das geht eleganter ...

 

Gruß.

 

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Warum sollte das Objekt, das für die Grafik zuständig ist, Bewegungsbefehle auslösen?

Aber mal ganz von vorne. Mit

vor 47 Minuten schrieb Sascha:

Was hast du also eigentlich vor?

meine ich nicht das Technische. Was soll an dieser Stelle in deinem Spiel passieren? Versuche das mal völlig ohne technische Begriffe zu beantworten. Soll ich etwas bewegen? Soll man auf etwas klicken können?

Was du da schreibst ist recht unverständlich, klingt aber stark nach gaaanz schlechter Vorgehensweise. Also lass uns doch mal ganz am Anfang anfangen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

"Warum sollte das Objekt, das für die Grafik zuständig ist, Bewegungsbefehle auslösen?"

Tut es ja nicht (das GO), sondern die Klasse, die das GO als Var enthält, tut das.

 

Aber von vorn, sorry das das alles so unverständlich ist :(  (bin rel. neu in oop und Unity, kann dafür aber noch ganz gut pascal und assembler :( )

 

Das Ziel ist ein kleines Game auf Hexfeldern,  auf dem sich  Einheiten bewegen und interagieren sollen.

 

Dazu dachte ich mir, kapsele ich sowohl jedes HexFeld als auch jede Einheit "Unit" als class mit versch. Methoden ("Move" z.B.) und verpasse diesem eine variable vom typ GO. welche die zugehörige  Grafik repräsentiert.

grob etwa so :

 

public class Unit {

public GameObject VUnit;    // UnitGrafik, durch "instantiate" aus prefab erzeugt

public bool moveUnit(param ...):    // bewegt EInheit, true wenn bewegt usw.

public bool killUnit()  // Einheit auflösen

... usw.

}

Ist das bereits falsch gekapselt ? 

Nun kann ich wie gesagt das GO, über welches die MAus grade überstreicht bekommen, aber nicht die Instanz der class "Unit" , die es beinhaltet...

Ohne das kann ich aber nicht die jeweiligen MEthoden ausführen, die etwas mit der Unit tun.

 

Gruß

 

 

 

 

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Okay, das bringt uns schon einmal weiter.

Du hast einen grundlegend ungünstigen Ansatz für Unity gewählt. Ein GameObject soll nicht nur eine Marionette für ein anderes Objekt sein, dass es steuert - es ist selbst ein Akteur. Anstatt also eine Klasse zu schreiben, die ein GameObject fernsteuert, baust du eine Komponente, die du auf das GameObject legst. Mit dieser steuert sich das GameObject dann selbst.

Statt also Folgendes zu schreiben:

class Unit
{
  public GameObject unit;
  
  public void TeleportTo(Vector3 target)
  {
    unit.transform.position = target;
  }
}

baust du so etwas:

public class Unit : MonoBehaviour
{
  public void TeleportTo(Vector3 target)
  {
    transform.position = target;
  }
}

Ein MonoBehaviour hat das GameObject auf dem es liegt und - noch viel wichtiger - die anderen Komponenten auf diesem GameObject immer Griffbereit. Du willst also nicht ein GameObject in eine eigene Klasse einbetten, sondern deine Klasse als Komponente zum Teil des GameObjects machen.

Dass du das so und nicht anders machen willst, liegt an dem einfachen Grundsatz: Arbeite immer mit deiner Umgebung (also in diesem Fall Unity), und nicht dagegen an.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja, ok, danke.

So ähnlich hatte ich es am Anfang, nämlich einen array mit den reinen Datenklassen und einen zweiten array mit den GOs.

Ich hab halt gelesen, dass es u.U. Sinn macht, die Datenklasse behalten zu können und nur das GameObject zerstören zu können.

Wie mache ich es, wenn meine Unit ausserhalb des Sichtradius liegt ,also kein GameObject dargestellt werden soll, aber weiterhin eine Simulation der Unit, z.B. Bewegung, stattfinden soll ?

Wenn ich das GameObject zerstöre , gehen in diesem Fall  ja auch alle Attribute  verloren.

Gruß 

 

PS :  Oder existiert im Typ GameObject eine Art "Schalter", der das Object  auf "invisible" stellt, den Rest aber unberührt lässt ?

PPS : Bin gerade am testen, hab meine class : Monobehaviour mit paar Variablen und Methoden gefüllt.

          Wie übergebe ich der Unit Parameter bei "instantiate" ?

          Bisher konnte ich das ja einfach mit new machen und die Parameter im Konstruktor mitgeben, aber standard Konstruktor Aufruf geht ja bei Monobehaviour nicht .

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hmm, so ganz check ichs noch nicht..

Meine class Unit : Monobehaviour binde ich wie genau an ein GameObject ? Mit AddComponent ? Wie übergebe ich Parameter bei Erzeugung ?

Könntest du mir noch etwas BeispielCode dafür geben ?

Generell dachte ich mir,  einen "Hashtable Units" zu erzeugen und eine neu erzeugte Unit mit

Units.Add(index,Unit)  oder Units.Add(index, GameObject) ??

darin aufzunehmen.

Würde das so gehen ?

 

Danke u.

Gruß

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 2 Stunden schrieb landvogt:

Ich hab halt gelesen, dass es u.U. Sinn macht, die Datenklasse behalten zu können und nur das GameObject zerstören zu können.

Wenn du so etwas liest, solltest du nicht gleich versuchen, das anzuwenden, ohne es zu hinterfragen. Wenn man mit Unity anfängt, sollte man sich komplett auf MonoBehaviour-Klassen beschränken. Du sagst selber, dass du noch recht neu bei der Sache bist - da solltest du nicht gleich versuchen abgefahrene Konzepte einzubauen.

vor 2 Stunden schrieb landvogt:

Wie mache ich es, wenn meine Unit ausserhalb des Sichtradius liegt ,also kein GameObject dargestellt werden soll, aber weiterhin eine Simulation der Unit, z.B. Bewegung, stattfinden soll ?

Nur, weil ein Renderer eines GameObjects nicht mehr sichtbar ist, heißt das nicht, dass das GameObject weg ist. Du musst also gar nichts besonderes machen.

vor 2 Stunden schrieb landvogt:

Wenn ich das GameObject zerstöre , gehen in diesem Fall  ja auch alle Attribute  verloren.

Warum zerstörst du das Objekt denn, wenn dessen besondere Eigenschaften noch wichtig sind?

vor 2 Stunden schrieb landvogt:

Oder existiert im Typ GameObject eine Art "Schalter", der das Object  auf "invisible" stellt, den Rest aber unberührt lässt ?

Mach dir darum mal keine Sorgen. Stelle dir die Szene wie eine echt Umgebung vor. Nur, weil die Kamera etwas nicht sieht, ist es nicht weg.

vor 2 Stunden schrieb landvogt:

Wie übergebe ich der Unit Parameter bei "instantiate" ?

Die Frage ergibt nicht viel Sinn. Schau dir mal Prefabs an. Da stellst du dir ein GameObject zusammen, mit dieser und jener Komponente, diese wiederum mit diesen und jenen Werten, und davon erstellst du mit Instantiate jeweils immer eine Kopie.

vor 1 Stunde schrieb landvogt:

Meine class Unit : Monobehaviour binde ich wie genau an ein GameObject ? Mit AddComponent ? Wie übergebe ich Parameter bei Erzeugung ?

Hier ist ein ganz grundlegender Denkfehler. Deine Grundannahme ist, dass du dein Spiel mit Code zusammenbaust. Das ist in Unity nicht die übliche Herangehensweise. Du baust dir deine Szene, deine Levels, deine Spielwelt(en) im Editor zusammen. Im Code beschreibst du nur, wie bestimmte Dinge sich verhalten.

Um eine Komponente auf ein GameObject zu legen, kannst du den "Add Component"-Knopf im Inspektor benutzen, wenn du das GameObejct markiert hast. Oder du ziehst die Script-Datei aus den Assets in den Inspektor.

vor 1 Stunde schrieb landvogt:

Generell dachte ich mir,  einen "Hashtable Units" zu erzeugen und eine neu erzeugte Unit mit

Warum? Welchen Zweck willst du damit erfüllen?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi Sascha, 

erst einmal vielen Dank für die ausführlichen Hinweise und Hilfe !

Versuche gerade das alles umzusetzen :

Zuerst habe ich ein "Empty" kreiert namens "Hex", dem habe ich mein "HexScript" angeheftet, eine class die von Monobehaviour erbt und einen Hexprefab - array enthält, sowie die Variablen q , r  , die das Hexfeld in der Map indizieren und int  Height.

Und eine methode Position();

Um die Map zu erzeugen, benutze ich zwei for Schleifen, die q und r durchlaufen lassen und jedesmal ein Hex instanzieren sollen;

Bisher hat das so funktioniert :

for q { for r {

AllHexes [q,r] = (GameObject)Instantiate (
            HexPrefab [Height],              // Terraintypen abh. von Höhe
            Positionqr(q,r),                      // Gamewelt-Vector-Methode, in Abh. von Position in Map
            rota); 

}}

Da das GO aber noch nicht existiert, kann Position() nicht aufgerufen werden.

Vorher war es so, dass Hex die Methode Position() bereitstellen konnte, da diese schon vor "instantiate" erzeugt war.

Wie löse ich das nun in diesem Fall, also wie erzeugt man nun innerhalb der Schleife jeweils ein GO und übergibt die nötigen Parameter ?

(Habe schon versucht "instantiate" in die start().Methode von HexScript zu verlagern, aber ohne Erfolg) 

 

LG

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich weiß ja nicht, was "Positionqr" so machen soll, aber prinzipiell brauchst du da doch nur einen Vector3 zu bauen:

new Vector3(q, r)

 

vor 1 Stunde schrieb landvogt:

Wie löse ich das nun in diesem Fall, also wie erzeugt man nun innerhalb der Schleife jeweils ein GO und übergibt die nötigen Parameter ?

Erstmal teilst du deine "Parameter" in zwei Teile auf: Diejenigen, die mehrere Objekte gemeinsam haben und diejenigen, die für jedes Objekt einzeln gesetzt werden müssen.

Was Objekte gemeinsam haben, landet einfach auf dem Prefab. Die Dinger haben alle ein Script "Feld"? "Feld" landet auf dem Prefab. Es gibt Waldfelder und Grasfelder? Mach dir mehrere Prefabs, und wähle, wie du es schon tust, das richtige für Instantiate aus.

Was die Objekte alle einzeln brauchen, kannst du nach Instantiate zuweisen. Der Rückgabewert von Instantiate ist eine Referenz auf das GameObject, das gerade instanziiert wurde oder auf eine Komponente davon - je nachdem, was du als Prefab-Parameter reingibst. Damit kannst du arbeiten:

var ball = Instantiate(ballPrefab, position, rotation);
ball.transform.localScale = Vector3.one * Random.Range(1f, 5f);

Hier spreche ich die Transform-Komponente des Balls an. Wenn du eine andere Komponente brauchst, hilft GetComponent:

var field = Instantiate(fieldPrefsb, position, rotation);
field.GetComponent<HexField>().Something();

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo Sascha,

 

also, erstmal vielen Dank an Dich und dieses Forum !

Endlich tut's das, was ich will :)

Ich habe jetzt an jedes Terrain-Prefab ein Script angeheftet, welches Methoden und Felder enthält.

Wenn ich jetzt mit der Maus über ein GO der Map streiche, gibt mir meine "Mausmanager".class   eine Referenz auf das GO zurück, über welches ich dann mit GetComponent

die Methoden und Felder des angehefteten Scripts abrufen kann,wie z.B die Indices des Hex im Map-array usw.. :)

Jetzt verstehe ich auf auch den Unterschied/Vorteil zu meine ursprüngliche Kapselung...

 

Also nochmal fettes THX ! :)  :)

und LG 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...