Wie erstelle ich ein neues GameObject, ohne es der Szene hinzuzufügen?

10

Ich erstelle im Wesentlichen mein eigenes Fertigsystem. Spielobjekte werden durch eine vom Menschen lesbare Datendatei definiert. Ich möchte ein leeres GameObject erstellen, es mit den in der Datendatei definierten Komponenten laden und es bereithalten und auf einen Instantiate()Anruf warten . Wenn ich jedoch GameObject go = new GameObject()ein neues Spielobjekt verwende, wird es der Szene hinzugefügt.

Mit in Preity integrierten Unity kann ich ein Fertighaus als GameObject laden und es wird nicht zur Szene hinzugefügt. (Siehe Beispiel unten)

Das Grundprinzip dahinter ist, dass ich eine Liste mit GameObjects haben möchte, von denen einige durch Laden von Unity-Prefabs und andere von meinem benutzerdefinierten Prefab-System erstellt wurden. Dies muss zur Laufzeit geschehen und kann den Unity-Editor nicht einbeziehen (da Endbenutzer im Idealfall ihre eigenen Datendateien definieren können).

Wie kann ich ein neues GameObject erstellen, ohne dass Unity es automatisch für mich instanziiert?


Zum Beispiel kann ich einen Anruf wie folgt tätigen:

Resources.LoadAll("PrefabsDirectory", typeof(GameObject))

Und ich bekomme eine Liste von GameObjects, von denen keines der Szene hinzugefügt wird, wenn der Anruf getätigt wird. Im Wesentlichen erstelle ich eine LoadAllMethode für meine eigenen Prefabs und möchte die GameObjects ebenfalls nicht instanziieren, wenn der Aufruf erfolgt.

MichaelHouse
quelle
1
Ich fürchte, du kannst nicht. Ich denke, Sie müssen die Instanziierung Ihrer Klasse verzögern.
Roberto
Es ist schon eine Weile her, dass ich Unity berührt habe, aber wenn sich herausstellt, dass es keinen Weg gibt, dies zu umgehen, können Sie das Objekt sofort danach aus der Szene entfernen und das gewünschte Ergebnis erzielen, nur ein wenig ineffizient?
Kevin Reid
@ KevinReid Ich glaube, der einzige Weg, dies zu tun, ist Destroydas GameObject aufzurufen. Dadurch wird es aus der Szene entfernt und freigegeben, wodurch es unbrauchbar wird.
MichaelHouse
1
@PandaPajama hat eine gute Idee. Das Aufrufen go.SetActive(false)ist der beste Weg, um so etwas wie einen Objektpool zu erstellen. Es ist nicht genau das, was Sie wollen, aber vielleicht könnten Sie eine kleine Gruppe inaktiver Objekte haben, die später für Ihre benutzerdefinierte Instanziierung geklont werden.
AndrewEkeren
1
@ Byte56: Warum genau möchten Sie Ihre benutzerdefinierten Fertighäuser vorinstanzieren und nicht nur den GO mit den erforderlichen Komponenten im laufenden Betrieb zusammenstellen, während Sie sie anhand eines fabrikähnlichen Musters instanziieren? Soweit ich weiß, möchten Sie Benutzern erlauben, Prefabs mit "ihren eigenen Datendateien" zu "serialisieren". Sie müssen diese Dateien also trotzdem zur Laufzeit lesen und die erforderlichen Komponenten instanziieren. Fehlt mir etwas?
Heisenbug

Antworten:

6

Sie könnten die hideFlags des GameObject ändern?

Ich habe gerade versucht, dies auszuführen:

GameObject myGameObject = new GameObject ();
myGameObject.name = "Obvious Name";

myGameObject.hideFlags = HideFlags.HideInHierarchy;

... und es ist da, aber es ist nicht in der Hierarchie. Technisch gesehen ist es in der Szene, aber Sie sehen es erst, wenn Sie die Flags wieder in HideFlags.None ändern. Es ist nicht die Antwort, nach der Sie suchen, aber zumindest was die Freigabe für Entwickler betrifft, ist es sauberer als das Gruppieren Ihrer Objekte.

Derivat
quelle
1
Dies könnte zusammen mit dem Deaktivieren (sodass keines der Skripte ausgeführt wird) funktionieren. Ich werde es versuchen und dich wissen lassen. Es ist immer noch eine Arbeit, aber ich denke, das ist es, was mir an diesem Punkt noch bleibt. Und soweit wir wissen, könnte dies das sein, was intern getan wird, obwohl ich es bezweifle.
MichaelHouse
1
@ Byte56: Ich dachte, es wäre auch eine Problemumgehung, aber ich habe heutzutage festgestellt, dass Unity genau das Gleiche bei der Vorschau von Animationen tut: Es instanziiert versteckte Spielobjekte in der Szene und rendert sie mit einer speziellen Kamera im Vorschaurahmen. Vielleicht klingt es nicht so sauber, aber tatsächlich scheint diese Lösung auch intern verwendet zu werden.
Heisenbug
1
Entschuldigung für die verspätete Annahme. Ich bin gerade erst dazu gekommen, dies umzusetzen, und es funktioniert großartig. Vielen Dank.
MichaelHouse
0

Genau das kann man leider nicht. Sie können jedoch dasselbe Entwurfsmuster (dh das Gebäude Ihrer Objekte abstrahieren und sie später einfach mit einem einzigen Befehl aufrufen) über ein Factory-Muster ausführen .

Wenn Sie ein Objekt möchten, rufen Sie so etwas auf Factory.CreateGameEntity(), und diese Methode behandelt alles hinter den Kulissen.

jhocking
quelle
Es ist komplexer als Sie vielleicht denken, was es nicht so sauber macht. Ich werde eine Antwort mit allen Details posten, aber im Wesentlichen muss der Parser ziemlich komplex sein. Wenn ich beispielsweise vor dem Instanziieren testen möchte, ob ein Fertighaus eine Komponente enthält, ist dies so einfach wie GetComponent<>() != null. Bei meinen Datendateien muss der Parser nach der richtigen Komponente in den Daten suchen. Gleiches gilt für das Abrufen eines Werts aus einer Komponente usw. Die GameObjectKlasse bietet viele Funktionen, die vom Parser dupliziert werden müssen.
MichaelHouse
Wenn Sie Beweise oder sogar eine Begründung dafür liefern können, warum dies nicht möglich ist, würde dies diese Antwort vervollständigen.
MichaelHouse
Ich werde später sehen, ob ich eine endgültige Dokumentation dazu finden kann. Im Moment kann ich nur diese Forenthreads finden. Forum.unity3d.com/threads/… - answers.unity3d.com/questions/366273/… - answers.unity3d .com / question / 19736 /…
jhocking
0

Es gibt keine Möglichkeit, go = new GameObject();ohne es der Szene hinzuzufügen.

Ich arbeite an einem RTS, bei dem die Spielerbasis dauerhaft sein muss. Im Wesentlichen serialisieren wir alles, was sie getan haben, und laden es zur Laufzeit mithilfe geänderter Assets aus dem Store wieder ein.

Die meisten werden in XML oder JSON ausgegeben, daher ist es ziemlich einfach, die Datei zu laden und nach Ihren Wünschen zu bearbeiten.

Mrk Fldig
quelle
Danke Marc. Können Sie Beweise oder Gründe dafür liefern, dass Sie kein neues GameObject erstellen können, ohne es der Szene hinzuzufügen? Ich habe einen eigenen Serialisierungscode, das ist also kein Problem, danke für den Vorschlag.
MichaelHouse
-1

Der richtige Weg ist, ein Fertighaus zu erstellen. Sie weisen dieses Fertighaus als Objekt zu. Wenn Sie es instanziieren möchten, verwenden Sie einfach die Referenz dieses Objekts und wandeln Sie es als GameObject um.

Ex :

private Object prefab;


public static GameObject Create(void)
{
   return (Instantiate(prefab , position , rotation) as GameObject);
}
Ericool
quelle
1
Dabei wird das vorhandene Fertighaussystem verwendet. Wie meine Frage besagt, erstelle ich im Wesentlichen mein eigenes Fertigsystem. Ein Teil der Anforderungen lautet "Der Unity-Editor kann nicht einbezogen werden". Beim Erstellen eines Fertighauses wird der Unity-Editor verwendet.
MichaelHouse
Damit Sie dies nicht tun können, benötigen Sie eine Lizenz für Entwickler, die das SDK verwenden, um dann Ihre eigenen Daten erstellen zu können. Wenn ich mich nicht irre, werden sie ihren Code nicht ohne bling bling teilen. Aber ich weiß, dass einige Leute Szenen aus Unity in ihre eigene Spiel-Engine
exportieren konnten
Nun, es ist eindeutig möglich, da ich mit der ausgewählten Antwort mein eigenes Fertigsystem erstellt habe. Wie das geht, erfahren Sie in dem Kurs, den ich in meinem Profil erstellt habe.
MichaelHouse
Nein, danke, ich bin ein graduierter Spielprogrammierer :) Nun, wenn es dir so gut gelingt, brauchst du es nicht, um Spiele zu machen
Ericool
Es ist ein System, mit dem Endbenutzer im Wesentlichen Fertighäuser herstellen können. Dies ist sehr nützlich in Spielen für Mods und andere vom Endbenutzer erstellte Inhalte. (Also ja, ich denke, es ist ziemlich nützlich, um Spiele zu machen).
MichaelHouse
-1

Um ein Fertighaus in eine Variable zu laden, damit Sie es später instanziieren können, verwenden Sie den folgenden Code:

 GameObject ball = (GameObject)(Resources.Load ("myPrefab"));

Ich habe dies in einem Projekt mit Unity 5.5 getan. Es kann instanziiert werden, jedoch nicht in der Szene oder einem Teil der Hierarchie, bis es wie gewohnt instanziiert wird.

Darthhawk
quelle
Ich habe das Gefühl, Sie haben die Frage falsch gelesen. Diese Antwort beinhaltet die Verwendung des Standard- Fertigsystems. Diese Frage wird im Zusammenhang mit der Erstellung eines benutzerdefinierten Fertigbausystems gestellt, auf das nicht zugegriffen werden kann. Das Beispiel unten dient dazu, dies weiter hervorzuheben.
Gnemlock
"Wie kann ich ein neues GameObject erstellen, ohne dass Unity es automatisch für mich instanziiert?" Ist die Frage, die gestellt wurde und dieser Code es beantwortet. Der Code kann geändert werden, um die gewünschten Ergebnisse mit benutzerdefinierten Ladesystemen zu erzielen.
Darthhawk
Dies ist im Wesentlichen das, was ich in dem in der Frage enthaltenen Beispiel beschreibe. Und es funktioniert gut für Fertighäuser, aber nicht zum Erstellen neuer Spielobjekte aus Datendateien.
MichaelHouse