2016-01-26 2 views
2

Voici une question très spécifique à laquelle j'ai eu du mal à répondre. J'ai un simple script qui crée/détruit un composant pendant veille/détruire dans le temps de l'exécution:Annuler la suppression de GameObject avec le script AddComponent dans Unity Editor (mode Lecture)

// Simple script that creates and destroys an AudioSource component in runtime. 
public class SimpleScript : MonoBehaviour { 
    // Runtime AudioSource component to be used. 
    private AudioSource source = null; 

    void Awake() { 
    source = gameObject.AddComponent<AudioSource>(); 
    source.hideFlags = HideFlags.HideAndDontSave; 
    } 

    void OnDestroy() { 
    Destroy(source); 
    } 

    void Update() { 
    // Do stuff with |source| . . . 
    } 
} 

Cependant, il fonctionne parfaitement bien avec la construction des exportations et tout, je l'ai remarqué récemment un cas très précis où agit l'unité un peu étrangement. Dans l'éditeur Unity (mode Lecture), si je supprime ce script (ou l'objet de jeu auquel le script est attaché), puis annulez l'opération, il en résulte deux AudioSource attachés à l'objet de jeu ressuscité. Plus précisement; un détruit par mon script précédemment avec l'opération de suppression + un créé avec le nouvel appel Awake. Et comme prévu, le faire à plusieurs reprises crée de plus en plus fuite des composants.

L'utilisation de différents HideFlags pour désactiver la sérialisation (?) Ne semble pas être utile, ni d'essayer DestroyImmediate etc. pour détruire le composant. Ma compréhension ici est que Unity traite le composant créé manuellement comme l'un des composants de GameObject, donc enregistre le détruire et l'annule en même temps que la suppression du script.

Des suggestions sur la façon de contourner/éviter ce comportement étrange de l'unité?

À la votre!

+0

Si vous recréer GameObject, pourquoi ne pas simplement le désactiver et le réactiver? – bpgeck

+0

Le problème ici est que vous n'avez pas le composant en premier lieu, c'est-à-dire que vous devez le créer quelque part dans le script afin de pouvoir l'activer/le désactiver. :) – anokta

Répondre

1

Vous avez répondu à votre question vous-même, @anokta! La méthode Awake() crée une source audio, c'est-à-dire la crée chaque fois que l'objet de jeu propriétaire est créé. Maintenant, lorsque vous supprimez manuellement l'objet de la vue hiérarchique (c'est-à-dire cliquez sur> Supprimer, etc.), puis et, vous appelez un mécanisme purement rédacteur de recréer cette dernière suppression. Cela va essentiellement recréer l'objet qui existait (jeu-objet avec le AudioSource ajouté). Et comme il s'agit maintenant d'un nouvel objet créé, il exécutera automatiquement sa méthode Awake() à nouveau. Je suis sûr que vous le saviez déjà et que vous étiez probablement à la recherche d'un moyen de contourner le problème. Supprimer des objets manuellement dans l'éditeur au moment de l'exécution est une zone délicate, et il y a un comportement bizarre sans fin qui peut être créé avec ça.

Si vous vouliez vraiment le contraindre, pourquoi ne pas définir un drapeau ailleurs (dans un gestionnaire global peut-être) qui est activé dès que le AddComponent<AudioSource>(); est appelé? à savoir

void Awake() { 
    if (globalManager.AsCreated != true) 
    { 
     source = gameObject.AddComponent<AudioSource>(); 
     source.hideFlags = HideFlags.HideAndDontSave; 
     globalManager.AsCreated = true; 
    } 
} 

globalManager est ... un gestionnaire global de quelque sorte. De cette façon, vous pouvez supprimer l'objet lors de l'exécution (ce que j'affirme toujours peut causer un comportement bizarre sans fin) et encore défaire pour le résultat que vous voulez. J'espère que cela aide!

+1

Tristement d'accord, peut-être que c'est * correct * de laisser cela se produire après tout. Je suppose que la solution de contournement du drapeau global peut être désordonnée lorsque plusieurs instances etc. sont impliquées. En dehors de cela, une autre solution de contournement que je peux penser en ce moment est de vérifier GetComponent avant d'ajouter le composant. Bien sûr, cela nous limiterait à un composant par objet de jeu alors - que l'OMI est encore moins * OK *. :) – anokta