Розробляючи гру в 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
видаляє компонент в кінці кадру (на відміну від Immediate
ly). DestroyImmediate
все одно вважається поганим стилем, але я думаю, що перехід Destroy
може фактично усунути ці помилки.