Розробляючи гру в Unity, я використовую ліберально, [RequireComponent(typeof(%ComponentType%))]щоб забезпечити, щоб у компонентах були виконані всі залежності.
Зараз я впроваджую навчальну систему, в якій висвітлюються різні об’єкти інтерфейсу. Щоб зробити виділення, я беру посилання на GameObjectсцену, потім клоную її за допомогою Instantiate (), а потім рекурсивно знімаю всі компоненти, які не потрібні для відображення. Проблема полягає в тому, що при ліберальному використанні RequireComponentцих компонентів багато хто не може бути просто видалений у будь-якому порядку, оскільки від них залежать інші компоненти, які ще не були видалені.
Моє запитання: чи є спосіб визначити, чи Componentможна видалити папку з того, до якого GameObjectвона приєднана.
Код, який я розміщую технічно, працює, однак він видає помилки Unity (не потрапляють у блок пробного лову, як видно із зображення
Ось код:
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);
}
}
Тож спосіб, з якого цей код генерував три останніх рядки журналу налагодження вище, виглядає наступним чином: Він взяв за вхід a GameObjectз двома компонентами: Buttonі PopupOpener. PopupOpenerвимагає, щоб Buttonкомпонент присутній у тому ж GameObject з:
[RequireComponent(typeof(Button))]
public class PopupOpener : MonoBehaviour
{
...
}
Перша ітерація циклу while (позначена текстом "ITERATION ON Button Invite (clone)") намагалася видалити Buttonпершу, але не змогла, оскільки це залежить від PopupOpenerкомпонента. це кинуло помилку. Потім він спробував видалити PopupOpenerкомпонент, який він зробив, оскільки від нього нічого не залежить. У наступній ітерації (позначеній другим текстом "ІТЕРАЦІЯ НА Кнопку запросити (клон)") вона спробувала видалити залишився Buttonкомпонент, який він тепер міг зробити, оскільки PopupOpenerбув видалений під час першої ітерації (після помилки).
Отже, моє питання полягає в тому, чи можна заздалегідь перевірити, чи можна вказаний компонент видалити зі свого струму GameObject, не викликаючи Destroy()або DestroyImmediate(). Дякую.
Destroyвидаляє компонент в кінці кадру (на відміну від Immediately). DestroyImmediateвсе одно вважається поганим стилем, але я думаю, що перехід Destroyможе фактично усунути ці помилки.
