Sviluppando un gioco in Unity, sto facendo un uso liberale [RequireComponent(typeof(%ComponentType%))]
per garantire che i componenti abbiano soddisfatto tutte le dipendenze.
Ora sto implementando un sistema tutorial che evidenzia vari oggetti dell'interfaccia utente. Per evidenziare, sto prendendo un riferimento a GameObject
nella scena, quindi lo clonio con Instantiate () e quindi rimuovo in modo ricorsivo tutti i componenti che non sono necessari per la visualizzazione. Il problema è che con l'uso liberale di RequireComponent
questi componenti, molti non possono essere semplicemente rimossi in qualsiasi ordine, poiché dipendono da altri componenti, che non sono stati ancora eliminati.
La mia domanda è: esiste un modo per determinare se un Component
può essere rimosso dal GameObject
quale è attualmente collegato.
Il codice che sto postando tecnicamente funziona, tuttavia genera errori Unity (non catturati nel blocco try-catch, come mostrato nell'immagine
Ecco il codice:
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);
}
}
Quindi il modo in cui questo codice ha generato le ultime tre righe del registro di debug sopra è il seguente: Ha preso come input a GameObject
con due componenti: Button
e PopupOpener
. PopupOpener
richiede che un Button
componente sia presente nello stesso GameObject con:
[RequireComponent(typeof(Button))]
public class PopupOpener : MonoBehaviour
{
...
}
La prima iterazione del ciclo while (indicato dal testo "Invito pulsante ITERATION ON (clone)") ha tentato di eliminare il Button
primo, ma non è stato possibile in quanto dipende dal PopupOpener
componente. questo ha gettato un errore. Quindi ha tentato di eliminare il PopupOpener
componente, cosa che ha fatto, poiché non dipende da altro. Nella successiva iterazione (indicata dal secondo testo "Invito pulsante ITERATION ON (clone)"), ha tentato di eliminare il Button
componente rimanente , cosa che ora poteva fare, poiché è PopupOpener
stato eliminato nella prima iterazione (dopo l'errore).
Quindi la mia domanda è se è possibile verificare in anticipo se un componente specificato può essere rimosso dalla sua corrente GameObject
, senza invocare Destroy()
o DestroyImmediate()
. Grazie.
Destroy
rimuove il componente alla fine del frame (al contrario di Immediate
ly). DestroyImmediate
è comunque considerato un cattivo stile, ma sto pensando che il passaggio a Destroy
potrebbe effettivamente eliminare questi errori.