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 GameObjectnella 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 RequireComponentquesti 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 Componentpuò essere rimosso dal GameObjectquale è 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 GameObjectcon due componenti: Buttone PopupOpener. PopupOpenerrichiede che un Buttoncomponente 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 Buttonprimo, ma non è stato possibile in quanto dipende dal PopupOpenercomponente. questo ha gettato un errore. Quindi ha tentato di eliminare il PopupOpenercomponente, 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 Buttoncomponente rimanente , cosa che ora poteva fare, poiché è PopupOpenerstato 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.
Destroyrimuove il componente alla fine del frame (al contrario di Immediately). DestroyImmediateè comunque considerato un cattivo stile, ma sto pensando che il passaggio a Destroypotrebbe effettivamente eliminare questi errori.
