Rozwijając grę w Unity, korzystam z niej [RequireComponent(typeof(%ComponentType%))]swobodnie, aby upewnić się, że wszystkie komponenty spełniają wszystkie zależności.
Wdrażam teraz system samouczka, który wyróżnia różne obiekty interfejsu użytkownika. Aby podświetlić, odnoszę się do GameObjectsceny, następnie klonuję ją za pomocą Instantiate (), a następnie rekurencyjnie usuwam wszystkie elementy, które nie są potrzebne do wyświetlania. Problem polega na tym, że przy swobodnym stosowaniu RequireComponentw tych komponentach wielu nie można po prostu usunąć w dowolnej kolejności, ponieważ zależą one od innych komponentów, które nie zostały jeszcze usunięte.
Moje pytanie brzmi: czy istnieje sposób, aby ustalić, czy Componentmożna usunąć z GameObjectniego, do którego jest on aktualnie podłączony.
Kod, który publikuję technicznie działa, jednak generuje błędy Unity (nie wychwycone w bloku try-catch, jak widać na obrazku
Oto kod:
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);
}
}
Tak więc sposób, w jaki ten kod wygenerował trzy ostatnie wiersze dziennika debugowania powyżej, wygląda następująco: Pobrano jako dane wejściowe GameObjectz dwoma składnikami: Buttoni PopupOpener. PopupOpenerRequies że Buttonskładnik ten występuje w tym samym GameObject'u z:
[RequireComponent(typeof(Button))]
public class PopupOpener : MonoBehaviour
{
...
}
Pierwsza iteracja pętli while (oznaczona tekstem „ITERATION ON Button Invite (clone)”) usiłowała usunąć Buttonpierwszą, ale nie mogła, ponieważ zależy od PopupOpenerkomponentu. to rzuciło błąd. Następnie próbował usunąć PopupOpenerkomponent, co zrobił, ponieważ nie zależy od niego nic innego. W następnej iteracji (oznaczonej drugim tekstem „ITERATION ON Button Invite (clone)”) próbował usunąć pozostały Buttonkomponent, co teraz mógł zrobić, ponieważ PopupOpenerzostał usunięty w pierwszej iteracji (po błędzie).
Moje pytanie brzmi więc, czy można z wyprzedzeniem sprawdzić, czy określony składnik można usunąć z bieżącego GameObject, bez wywoływania Destroy()lub DestroyImmediate(). Dziękuję Ci.
Destroyusuwa komponent na końcu ramki (w przeciwieństwie do Immediately). DestroyImmediatei tak jest uważany za zły styl, ale myślę, że przejście na Destroymoże faktycznie wyeliminować te błędy.
