Comment créer un nouveau GameObject, sans l'ajouter à la scène?


10

Je crée ce qui est essentiellement mon propre système préfabriqué. Les objets de jeu sont définis par un fichier de données lisibles par l'homme. Je voudrais créer un GameObject vide, le charger avec les composants définis dans le fichier de données et l'avoir prêt et en attente d'un Instantiate()appel. Cependant, chaque fois que j'utilise GameObject go = new GameObject()un nouvel objet de jeu est ajouté à la scène.

En utilisant Unity intégré dans les préfabriqués, je peux charger un préfabriqué en tant que GameObject, et il n'est pas ajouté à la scène. (Voir l'exemple ci-dessous)

La raison derrière cela est que j'aimerais avoir une liste qui contient GameObjects, certains générés par le chargement de préfabriqués Unity et d'autres créés par mon système de préfabriqués personnalisés. Cela doit se produire au moment de l'exécution et ne peut pas impliquer l'éditeur Unity (car, idéalement, les utilisateurs finaux pourraient définir leurs propres fichiers de données).

Comment puis-je créer un nouveau GameObject sans que Unity l'instancie automatiquement pour moi?


Par exemple, je peux faire un appel comme celui-ci:

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

Et je vais obtenir une liste de GameObjects, dont aucun n'est ajouté à la scène lorsque l'appel est effectué. Essentiellement, je crée une LoadAllméthode pour mes propres préfabriqués, et de même, je ne veux pas instancier les GameObjects lorsque l'appel est effectué.


1
Je crains que vous ne puissiez pas. Je pense que vous devrez retarder l'instanciation de votre classe.
Roberto

Cela fait un moment que je n'ai pas touché Unity, mais s'il s'avère qu'il n'y a pas de moyen de contourner cela, pourriez-vous simplement retirer l'objet de la scène immédiatement après et obtenir le résultat souhaité, juste légèrement inefficace?
Kevin Reid

@KevinReid Je crois que la seule façon de le faire est d'appeler Destroyle GameObject. Ce qui le supprime de la scène et le libère, le rendant inutilisable.
MichaelHouse

1
@PandaPajama a une bonne idée. L'appel go.SetActive(false)est le meilleur moyen de créer quelque chose comme un pool d'objets. Ce n'est pas exactement ce que vous voulez, mais vous pourriez peut-être avoir un petit groupe d'objets inactifs qui seront ensuite clonés pour votre instanciation personnalisée.
AndrewEkeren

1
@ Byte56: Pourquoi voulez-vous exactement pré-instancier vos préfabriqués personnalisés et ne pas simplement composer le GO avec les composants requis à la volée tout en les instanciant en utilisant un modèle d'usine? Pour ce que j'ai compris, vous voulez permettre aux utilisateurs de "sérialiser" les préfabriqués en utilisant "leurs propres fichiers de données", vous devez donc lire ces fichiers au moment de l'exécution de toute façon et instancier les composants requis.
Heisenbug

Réponses:


6

Vous pouvez changer les hideFlags du GameObject?

J'ai juste essayé de faire ça:

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

myGameObject.hideFlags = HideFlags.HideInHierarchy;

... et c'est là, mais ce n'est pas dans la hiérarchie. Techniquement, c'est dans la scène, mais vous ne le voyez pas jusqu'à ce que vous remettiez ses drapeaux à HideFlags.None. Ce n'est pas la réponse que vous cherchez, mais au moins en ce qui concerne la publication aux développeurs, c'est plus propre que de regrouper vos objets.


1
Ceci, associé à sa désactivation (donc aucun des scripts ne s'exécute), pourrait fonctionner. Je vais essayer et je vous le ferai savoir. C'est toujours un travail, mais je pense que c'est ce qui me reste à ce stade. Et, pour tout ce que nous savons, cela pourrait être ce qui se fait en interne, bien que j'en doute.
MichaelHouse

1
@ Byte56: Je pensais que c'était aussi une solution de contournement, mais j'ai découvert ces jours-ci qu'Unity fait exactement la même chose lors de la prévisualisation des animations: il instancie un objet de jeu caché dans la scène et les rend dans le cadre d'aperçu avec un appareil photo dédié. Alors peut-être que cela ne semble pas si propre, mais en fait, cette solution semble également être utilisée en interne.
Heisenbug

1
Désolé pour le retard accepter. Je viens de commencer à mettre en œuvre cela et cela fonctionne très bien. Merci.
MichaelHouse

0

Vous ne pouvez pas faire exactement cela, malheureusement. Cependant, vous pouvez accomplir le même modèle de conception (c.-à-d. En éloigner la construction de vos objets, puis les appeler simplement avec une seule commande plus tard) via un modèle d'usine .

Lorsque vous voulez un objet, appelez quelque chose comme Factory.CreateGameEntity(), et cette méthode gérera tout dans les coulisses.


C'est plus complexe que vous ne le pensez, ce qui le rend moins propre. Je posterai une réponse avec tous les détails, mais essentiellement l'analyseur doit être assez complexe. Par exemple, si je veux tester si un préfabriqué a un composant, avant d'instancier, c'est aussi simple que GetComponent<>() != null. Avec mes fichiers de données, l'analyseur doit rechercher le composant correct dans les données. Idem pour obtenir une valeur à l'intérieur d'un composant, etc. La GameObjectclasse fournit de nombreuses fonctionnalités qui doivent être dupliquées par l'analyseur.
MichaelHouse

Si vous pouvez fournir des preuves ou même des raisons pour lesquelles cela ne peut pas être fait, cela rendrait cette réponse complète.
MichaelHouse

Je verrai plus tard si je peux trouver une documentation définitive à ce sujet, pour l'instant tout ce que je peux trouver sont ces fils de discussion forum.unity3d.com/threads/… - answers.unity3d.com/questions/366273/… - answers.unity3d .com / questions / 19736 /…
jhocking

0

Il n'y a aucun moyen de le faire go = new GameObject();sans l'ajouter à la scène.

Je travaille sur un RTS où la base de joueurs doit être persistante, et essentiellement, nous sérialisons tout ce qu'ils ont fait et le rechargeons au moment de l'exécution en utilisant des actifs modifiés du magasin.

La plupart des sorties en XML ou JSON, il est donc assez simple de charger le fichier et de le manipuler comme vous le souhaitez.


Merci Marc. Pouvez-vous fournir des preuves ou une justification pour ne pas pouvoir créer un nouveau GameObject sans l'ajouter à la scène? J'ai mon propre code de sérialisation, donc ce n'est pas un problème, merci pour la suggestion.
MichaelHouse

-1

La bonne façon est de faire un préfabriqué, vous allouez ce préfabriqué en tant qu'objet, puis chaque fois que vous voulez instancier, utilisez simplement la référence de cet objet et convertissez-le en GameObject.

ex:

private Object prefab;


public static GameObject Create(void)
{
   return (Instantiate(prefab , position , rotation) as GameObject);
}

1
Cela utilise le système préfabriqué existant. Comme l'indique ma question, je crée essentiellement mon propre système préfabriqué. Une partie des exigences est "ne peut pas impliquer l'éditeur Unity". La création d'un préfabriqué utilise l'éditeur Unity.
MichaelHouse

Ce que vous ne pouvez pas faire, vous auriez besoin d'une licence pour qu'un développeur utilisant son SDK puisse ensuite créer vos propres données. Sauf erreur, ils ne partageront pas leur code sans bling bling. Mais je sais que certaines personnes ont pu exporter des scènes d'Unity vers leur propre moteur de jeu
Ericool

Eh bien, c'est clairement possible puisque j'ai créé mon propre système préfabriqué en utilisant la réponse sélectionnée. Vous pouvez apprendre à le faire dans le cours que j'ai créé, trouvé dans mon profil.
MichaelHouse

non merci je suis un programmeur de jeux diplômé :) Eh bien, si vous réussissez aussi bien pour vous, n'en avez pas besoin pour faire des jeux
Ericool

C'est un système qui permet essentiellement aux utilisateurs finaux de faire des préfabriqués. C'est assez utile dans les jeux pour mods et autres contenus créés par l'utilisateur final. (Alors oui, je pense que c'est assez utile pour faire des jeux).
MichaelHouse

-1

Pour charger un préfabriqué dans une variable afin de pouvoir l'instancier plus tard, vous utiliseriez le code suivant:

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

Je l'ai fait dans un projet avec Unity 5.5. Il sera disponible pour instancier mais pas dans la scène ou une partie de la hiérarchie jusqu'à ce qu'il soit instancié normalement.


J'ai l'impression que vous avez mal lu la question. Cette réponse implique l'utilisation du système préfabriqué par défaut . Cette question se pose dans le contexte de la création d'un système préfabriqué personnalisé , où celui-ci n'est pas accessible. L'exemple en bas sert à le souligner davantage.
Gnemlock

"Comment puis-je créer un nouveau GameObject sans que Unity l'instancie automatiquement pour moi?" C'est la question qui a été posée et ce code y a répondu. Le code peut être modifié pour obtenir les résultats souhaités avec des systèmes de chargement personnalisés.
darthhawk

C'est essentiellement ce que je décris dans l'exemple inclus dans la question. Et cela fonctionne bien pour les préfabriqués, mais pas pour créer de nouveaux objets de jeu à partir de fichiers de données.
MichaelHouse
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.