En développant un jeu dans Unity, je fais un usage libéral de [RequireComponent(typeof(%ComponentType%))]
pour assurer que les composants ont toutes les dépendances respectées.
J'implémente maintenant un système de tutoriel qui met en évidence divers objets d'interface utilisateur. Pour faire la mise en surbrillance, je prends une référence au GameObject
dans la scène, puis je le clone avec Instantiate (), puis je supprime récursivement tous les composants qui ne sont pas nécessaires pour l'affichage. Le problème est qu'avec l'utilisation libérale de RequireComponent
dans ces composants, beaucoup ne peuvent pas être simplement supprimés dans n'importe quel ordre, car ils dépendent d'autres composants, qui n'ont pas encore été supprimés.
Ma question est la suivante: existe-t-il un moyen de déterminer si un Component
peut être supprimé du fichier auquel GameObject
il est actuellement attaché?
Le code que je publie fonctionne techniquement, mais il génère des erreurs Unity (pas pris dans le bloc try-catch, comme on le voit dans l'image
Voici le code:
public void StripFunctionality(RectTransform rt)
{
if (rt == null)
{
return;
}
int componentCount = rt.gameObject.GetComponents<Component>().Length;
int safety = 10;
int allowedComponents = 0;
while (componentCount > allowedComponents && safety > 0)
{
Debug.Log("ITERATION ON "+rt.gameObject.name);
safety--;
allowedComponents = 0;
foreach (Component c in rt.gameObject.GetComponents<Component>())
{
//Disable clicking on graphics
if (c is Graphic)
{
((Graphic)c).raycastTarget = false;
}
//Remove components we don't want
if (
!(c is Image) &&
!(c is TextMeshProUGUI) &&
!(c is RectTransform) &&
!(c is CanvasRenderer)
)
{
try
{
DestroyImmediate(c);
}
catch
{
//NoOp
}
}
else
{
allowedComponents++;
}
}
componentCount = rt.gameObject.GetComponents<Component>().Length;
}
//Recursive call to children
foreach (RectTransform childRT in rt)
{
StripFunctionality(childRT);
}
}
Ainsi, la façon dont ce code a généré les trois dernières lignes du journal de débogage ci-dessus est la suivante: il a pris comme entrée a GameObject
avec deux composants: Button
et PopupOpener
. PopupOpener
requiert qu'un Button
composant soit présent dans le même GameObject avec:
[RequireComponent(typeof(Button))]
public class PopupOpener : MonoBehaviour
{
...
}
La première itération de la boucle while (indiquée par le texte "ITERATION ON Button Invite (clone)") a tenté de supprimer la Button
première, mais n'a pas pu car elle dépend du PopupOpener
composant. cela a jeté une erreur. Ensuite, il a tenté de supprimer le PopupOpener
composant, ce qu'il a fait, car il ne dépend d'aucune autre chose. Dans l'itération suivante (désignée par le deuxième texte "ITERATION ON Button Invite (clone)"), il a tenté de supprimer le Button
composant restant , ce qu'il pouvait maintenant faire, car il PopupOpener
avait été supprimé lors de la première itération (après l'erreur).
Ma question est donc de savoir s'il est possible de vérifier à l'avance si un composant spécifié peut être supprimé de son courant GameObject
, sans invoquer Destroy()
ou DestroyImmediate()
. Je vous remercie.
Destroy
supprime le composant à la fin du cadre (par opposition à Immediate
ly). DestroyImmediate
est considéré comme un mauvais style de toute façon, mais je pense que le passage à Destroy
peut effectivement éliminer ces erreurs.