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 GameObject
sceny, 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 RequireComponent
w 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 Component
można usunąć z GameObject
niego, 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 GameObject
z dwoma składnikami: Button
i PopupOpener
. PopupOpener
Requies że Button
skł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ąć Button
pierwszą, ale nie mogła, ponieważ zależy od PopupOpener
komponentu. to rzuciło błąd. Następnie próbował usunąć PopupOpener
komponent, 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 Button
komponent, co teraz mógł zrobić, ponieważ PopupOpener
został 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.
Destroy
usuwa komponent na końcu ramki (w przeciwieństwie do Immediate
ly). DestroyImmediate
i tak jest uważany za zły styl, ale myślę, że przejście na Destroy
może faktycznie wyeliminować te błędy.