Разрабатывая игру в Unity, я свободно использую ее, [RequireComponent(typeof(%ComponentType%))]чтобы обеспечить соответствие всех компонентов.
Сейчас я реализую учебную систему, которая выделяет различные объекты пользовательского интерфейса. Чтобы сделать выделение, я беру ссылку на GameObjectсцену, затем клонирую ее с помощью Instantiate () и затем рекурсивно удаляю все компоненты, которые не нужны для отображения. Проблема заключается в том, что при свободном использовании RequireComponentэтих компонентов многие не могут быть просто удалены в любом порядке, поскольку они зависят от других компонентов, которые еще не были удалены.
Мой вопрос: есть ли способ определить, Componentможно ли удалить объект из того, к которому GameObjectон прикреплен.
Код, который я публикую, технически работает, однако он выдает ошибки Unity (не зафиксированные в блоке try-catch, как видно на рисунке).
Вот код:
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);
}
}
Таким образом, этот код сгенерировал последние три строки в журнале отладки, описанные выше: он принимается в качестве входных данных GameObjectс двумя компонентами: Buttonи PopupOpener. PopupOpenerтребует, чтобы Buttonкомпонент присутствовал в том же GameObject с:
[RequireComponent(typeof(Button))]
public class PopupOpener : MonoBehaviour
{
...
}
Первая итерация цикла while (обозначается текстом «Кнопка приглашения ITERATION ON (клон)») пыталась удалить Buttonпервую, но не смогла, так как это зависит от PopupOpenerкомпонента. это бросило ошибку. Затем он попытался удалить PopupOpenerкомпонент, что он и сделал, так как от него больше ничего не зависит. На следующей итерации (обозначается вторым текстом «Кнопка приглашения ITERATION ON (клон)») она попыталась удалить оставшийся Buttonкомпонент, который он теперь мог сделать, поскольку он PopupOpenerбыл удален на первой итерации (после ошибки).
Поэтому мой вопрос заключается в том, можно ли заранее проверить, можно ли удалить указанный компонент из его текущего GameObject, без вызова Destroy()или DestroyImmediate(). Спасибо.
Destroyудаляет компонент в конце кадра (в отличие от Immediately). DestroyImmediateв любом случае считается плохим стилем, но я думаю, что переключение на Destroyможет на самом деле устранить эти ошибки.
