Jump to content
Unity Insider Forum
LarsB

Arbeiten mit ChildObjects

Recommended Posts

Guten Morgen zusammen,

ich fange gerade an, mit Unity zu arbeiten. Daher würde ich mich darüber freuen, wenn ihr mir Rückmeldung geben könntet, ob der nachfolgend beschriebene Weg für mein Problem der richtige ist oder ob ihr andere Lösungsmöglichkeiten habt.

Zentraler Bestandteil meines Projekts sind Farbfelder, die (bislang) fünf verschiedene Farben annehmen können. Allerdings kann das Farbfeld weitere Elemente haben. So kann das Farbfeld an jeder Seite eine Ein- oder Ausgangspipelines haben. Außerdem können sich der Rand und der Hintergrund der Pipeline farblich ändern.

Insgesamt kommt man so auf bis zu 11 verschiedene Elemente, die 5 verschiedene Farben annehmen können. Wenn ich mich nicht verrechnet habe, wären also 161.051 Kombinationen möglich.

Es macht natürlich keinen Sinn, so viele GameObjects zu erstellen. Ich habe mich daher dazu entschieden, mit ChildObjects zu arbeiten. Das GameObject „Farbfeld“ hat also mehrere ChildObjects, welche die einzelnen Elemente (Pipelines, Farbfeld, Rand, Hintergrund) repräsentieren. Aus dem GameObject „Farbfeld“ mit seinen Child-Objekten habe ich ein Prefab erstellt, mit denen ich zur Laufzeit das Spielfeld erstelle:

GameObject newColorField = Instantiate(color_field, new Vector3(startX + (xOffset * x), startY + (yOffset * y), 0), color_field.transform.rotation);

Das ChildObject definiere ich in der Awake-Methode:

private GameObject oben = null;

void Awake() {

	oben = this.gameObject.transform.Find("oben").gameObject;

}

Sollte das GameObject bestimmte Elemente nicht haben, also z.B. oben keine Pipeline, dann deaktiviere ich diese:

this.gameObject.transform.Find("oben").gameObject.SetActive(false);

Wenn eine Pipeline eine bestimmte Farbe annimmt, tausche ich das Sprite aus (ich arbeite mit Sprites, da ich diese animieren möchte, um den Farbverlauf darzustellen):

public Sprite oben_rot;

private void change_color() {

	oben.GetComponent<SpriteRenderer>().sprite = oben_rot;

}

Das funktioniert auch alles soweit. Meine Frage wäre aber: Ist das für euch ein gangbarer Weg? Oder habt ihr einen anderen, besseren Weg? Gibt es vergleichbare Projekte, die es anders gelöst haben?

Danke schon einmal für eure Hilfe.

Viele Grüße

Lars

Share this post


Link to post
Share on other sites

Wenn ich alles richtig verstehe, dann ist der Weg schon gar nicht schlecht. Ich persönlich halte es immer für sehr gefährlich, wenn man die Find-Methode nutzt, da Du so nicht mehr in der Lage bist, Objekte umzubenennen, ohne Code zu ändern.

Zudem sind die Find-Methoden relativ langsam, wenn man sie oft "auf einmal" aufruft, z.B. im Update().

Hier würde ich eher sowas machen:

public GameObject oben;
//...
oben.SetActive(false);

Dann kannst Du im Inspector dein "oben" Objekt zuweisen und direkt im Skript nutzen.

Share this post


Link to post
Share on other sites

Ich vergaß noch zu erwähnen: Das ChildObject definiere ich in der Awake-Methode:

private GameObject oben = null;

void Awake() {

	oben = this.gameObject.transform.Find("oben").gameObject;

}

Habe meinen Beitrag entsprechend geändert.

Du schreibst, dass die Find-Methode relativ langsam sei. Wie komme ich sonst - schneller - an das ChildObject?

Share this post


Link to post
Share on other sites
oben = this.gameObject.transform.GetChild(0).gameObject;

... ginge auch. In diesem Fall müsste man nur aufpassen, dass man die Sortierung der ChildObjects nicht verändert.

Wäre die GetChild-Methode schneller als die Find-Methode?

Share this post


Link to post
Share on other sites

Du hast den entscheidenden Teil von @devandarts Post übersehen:

vor 2 Stunden schrieb devandart:

Dann kannst Du im Inspector dein "oben" Objekt zuweisen und direkt im Skript nutzen.

Wenn ein Feld in einer Klasse wie MonoBehaviour public ist, dann wird es im Editor angezeigt, wenn du im Inspektor die Komponente anschaust. Bei primitiven Typen wie Zahlen kannst du dann eine Nummer eintippen. Bei Referenztypen, die Unity-Objekte referenzieren (wie GameObject) kannst du ein entsprechendes Objekt per Drag and Drop in das Feld ziehen.

Wenn dein Objekt instanziiert wird, dann deserialisiert Unity die so eingestellten Referenzen, bevor Awake überhaupt aufgerufen wird. Das bedeutet, dass der von @devandart gepostete Code alles ist, was du brauchst. Wenn du das richtige GameObject im Inspektor in dein Objekt gezogen hast, dann wird auch das richtige Objekt automagisch referenziert sein, sobald Unity mit instaziieren fertig ist.

  • Like 1

Share this post


Link to post
Share on other sites

Was man hier aus Code Design Sicht noch beachten kann ist, dass eine public Variable von allem anderen Code manipuliert werden kann. Dies passiert auch gerne unabsichtlich und endet in stundenlangem Debugging.

Wenn man es ganz sauber gekapselt haben möchte, damit kein fremder Code (z.B. andere Komponenten) bestimmte Felder manipuliert, kann man im Inspector auch private Felder zugänglich machen.

Dafür musst Du Unity lediglich mitteilen, dass Du das private Feld serialisieren möchtest.

using System;
//...
[SerializeField]
private GameObject oben;
//...

Nun kannst Du das Feld auch im Editor per Drag and Drop zuweisen, aber nicht von anderen Komponenten aus.

Share this post


Link to post
Share on other sites
vor 1 Stunde schrieb devandart:

Was man hier aus Code Design Sicht noch beachten kann ist, dass eine public Variable von allem anderen Code manipuliert werden kann. Dies passiert auch gerne unabsichtlich und endet in stundenlangem Debugging.

Wenn man es ganz sauber gekapselt haben möchte, damit kein fremder Code (z.B. andere Komponenten) bestimmte Felder manipuliert, kann man im Inspector auch private Felder zugänglich machen.

Dafür musst Du Unity lediglich mitteilen, dass Du das private Feld serialisieren möchtest.


using System;
//...
[SerializeField]
private GameObject oben;
//...

Nun kannst Du das Feld auch im Editor per Drag and Drop zuweisen, aber nicht von anderen Komponenten aus.

Danke für den Tipp. Das macht sicher Sinn...

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...