Очистка списка и повторное добавление объектов приводит к тому же количеству объектов? - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть List, в котором хранятся все child gameobjects.

List<GameObject> goChildren = new List<GameObject>();

В функции Start () у меня есть это:

foreach (Transform child in transform)
{
    goChildren.Add(child.gameObject);
}

, чтобы добавить всех детей.

Тогда у меня есть метод «Hit ()», который вызывается, когда игрок нажимает на один из дочерних объектов.

Затем дочерний объект должен быть уничтожен, список должен быть очищен, и все оставшиеся объекты должны быть добавлены снова.

Вот как я пытаюсь справиться с этим:

Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, actionRange))
{
    Destroy(hit.transform.gameObject);
}

goChildren.Clear();
foreach (Transform child in transform)
{
    goChildren.Add(child.gameObject);
}

Но тогда у меня в списке goChildren хранится то же количество объектов, что и раньше.

Я использовал Debug.Log(goChildren.Count), чтобы отобразить количество детей до Hit () - Method и после него.

И оба говорят мне, что у меня в списке 566 детей.

Я думал, что этот код должен делать:

  1. Уничтожить одного ребенка
  2. Очистить список
  3. Добавить оставшихся детейв список

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Как вы можете прочитать здесь , уничтожение объекта происходит после текущего цикла обновления.Таким образом, на самом деле объект все еще существует (и элемент списка преобразования имеет ссылку на него) в тот момент, когда вы пополняете список.Поэтому лучшим решением будет удалить ссылку на элемент из списка на

goChildren.Remove(***obj reference***)

или

goChildren.RemoveAt(***obj index***)

, а затем уничтожить игровой объект.Кроме того, нет смысла удалять и считывать неизмененные изменения, он генерирует множество ненужных модификаций массива за кулисами без причины.(Функции Remove и RemoveAt также копируют смещенную часть после удаленного элемента, что может быть огромной работой, если удаленный элемент находится в начале большого списка.)

Обратите внимание, что добавление огромного количества элементовновый список крайне неоптимален, так как массив за списком перераспределяется и копируется снова и снова.Емкость списка по умолчанию равна 4, и когда размер превышает его, он выделяет новый массив размером 8, а затем копирует содержимое.То же самое происходит с 16, 32, 64 и т. Д., Поэтому, когда вы заполняете список от 0 до 566 элементов,

  1. выделяет 4
  2. выделяет 8, копирует
  3. выделяет 16, копия
  4. 32, копия
  5. 64, копия
  6. 128, копия
  7. 256, копия
  8. 512, копия
  9. 1024, копия

Источник

Вы можете предварительно выделить список с помощью

List<GameObject> goChildren = new List<GameObject>(capacity);

, но этоэто просто начальный прирост производительности, попробуйте использовать

HashSet<T>

, если порядок элементов не важен.Все, что вам нужно, это хорошая функция хеширования, которая в большинстве случаев может быть легко реализована.

0 голосов
/ 30 ноября 2018

Попробуйте это:

    Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, actionRange))
{
    goChildren.Remove(hit.transform.gameObject);
    Destroy(hit.transform.gameObject);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...