Ich entwickle ein Spiel in Unity und nutze es liberal, [RequireComponent(typeof(%ComponentType%))]um sicherzustellen, dass die Komponenten alle Abhängigkeiten erfüllen.
Ich implementiere jetzt ein Tutorial-System, das verschiedene UI-Objekte hervorhebt. Um die Hervorhebung durchzuführen, verweise ich auf die GameObjectin der Szene, klone sie dann mit Instantiate () und entferne rekursiv alle Komponenten, die für die Anzeige nicht benötigt werden. Das Problem ist, dass bei der liberalen Verwendung RequireComponentdieser Komponenten viele nicht einfach in beliebiger Reihenfolge entfernt werden können, da sie von anderen Komponenten abhängen, die noch nicht gelöscht wurden.
Meine Frage ist: Gibt es eine Möglichkeit festzustellen, ob ein Componentaus dem GameObjectaktuell angehängten entfernt werden kann?
Der Code, den ich veröffentliche, funktioniert technisch, löst jedoch Unity-Fehler aus (nicht im Try-Catch-Block abgefangen, wie im Bild dargestellt)
Hier ist der 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);
}
}
Die Art und Weise, wie dieser Code die letzten drei Zeilen des obigen Debug-Protokolls generiert hat, ist die folgende: Als Eingabe wurde a GameObjectmit zwei Komponenten verwendet: Buttonund PopupOpener. PopupOpenererfordert, dass eine ButtonKomponente in demselben GameObject vorhanden ist mit:
[RequireComponent(typeof(Button))]
public class PopupOpener : MonoBehaviour
{
...
}
Bei der ersten Iteration der while-Schleife (gekennzeichnet durch den Text "ITERATION ON Button Invite (Klon)") wurde versucht, die Buttonerste zu löschen , dies konnte jedoch nicht, da dies von der PopupOpenerKomponente abhängt . Dies warf einen Fehler. Dann wurde versucht, die PopupOpenerKomponente zu löschen , was auch der Fall war, da sie von nichts anderem abhängig ist. In der nächsten Iteration (gekennzeichnet durch den zweiten Text "ITERATION ON Button Invite (Klon)") wurde versucht, die verbleibende ButtonKomponente zu löschen , was jetzt möglich war, da PopupOpenersie in der ersten Iteration (nach dem Fehler) gelöscht wurde.
Meine Frage ist also, ob es möglich ist, im Voraus zu prüfen, ob eine bestimmte Komponente aus ihrer aktuellen entfernt werden kann GameObject, ohne Destroy()oder aufzurufen DestroyImmediate(). Vielen Dank.
Destroyentferne aber die Komponente am Ende des Rahmens (im Gegensatz zu Immediately). DestroyImmediatewird sowieso als schlechter Stil angesehen, aber ich denke, ein Wechsel zu Destroykann diese Fehler tatsächlich beseitigen.
