NULL который не NULL или как подписаться на GameObject.OnDes

Программирование на Юнити.

NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение DrMort 23 окт 2019, 11:18

Затравка. Есть у нас gameObject на сцене. На нем висят какие то компоненты, всё это крутится и работает. Красота.
Есть у нас триггер со скриптом, который отслеживает входящие gameObject и выходящие из зоны триггер коллайдера соответственно по OnTriggerEnter и OnTriggerExit. Пока gameObject в триггерной зоне каждый апдейт с ним чего то происходит. Для этого в скрипте триггерной зоны висит тупо List<GameObject> и простая переборка по итератору.
Всё крутится и работает, красота. Теперь возьмём и сделаем Destroy(gameObject). На сцене его нет. В List<GameObject> триггерной зоны остался один item который равен null. Но не совсем. Все его свойства по прежнему доступны. Если взять от него GetComponent<MyScript>() то он сработает и вернёт null у которого все поля остались на месте и с ними как ни странно можно работать.
С разработчиками связался, они говорят что уничтожение объекта в Unity не эквивалентно уничтожению объекта в С#. Что как бы с одной стороны логично, но порождает определенную проблему отслеживания что гавкнулось, а что всё ещё актуально.
Можно проверить что item==null и не обрабатывать его, не вопрос, но память не резиновая - GC её не освободит, но даже попытка вычистить все null из всех списков тратит ресурсы да и не всегда возможна.
А есть ли возможность подписаться на GameObject.OnDestroy()? Не компонента, а именно GameObject?
Кто нибудь знает законный мануальный способ отследить событие GameObject.OnDestroy()?
DrMort
UNец
 
Сообщения: 28
Зарегистрирован: 08 фев 2013, 08:35

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение Xtir 23 окт 2019, 11:34

Синтаксис:
Используется csharp
public class MyObject : MonoBehaviour
{
    Trigger trigger;
    private void OnDestroy()
    {
        trigger.ObjectDestroyed(this);
    }
}

public class Trigger : MonoBehaviour
{
    public List<MyObject> list;

    private void Update()
    {
        foreach(MyObject obj in list)
        {
            //что-то делаем с нашими объектами
        }
    }

    public void ObjectDestroyed(MyObject obj)
    {
        list.Remove(obj);
    }
}


Можно сделать что-то типа такого. Когда объект попадает в триггер, он записывает к себе этот триггер(соответсвенно триггер добавляет этот объект в список к себе), а когда уничтожается вызывает метод триггера который удалит его из списка объектов которые находятся в триггере.
Xtir
UNIверсал
 
Сообщения: 498
Зарегистрирован: 21 окт 2016, 00:37

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение DrMort 23 окт 2019, 11:38

Неа, не прокатит. На GameObject может вообще не быть скриптов, ни одного. Вешать скрипт в котором будет только этот функционал на всё подряд - как то пошло.
Сейчас думаю в сторону расширения базового функционала GameObject.
Плюс gameObject не обязательно будет только в одном List<> одного скрипта. Теоретически их может быть сколько угодно, тогда придётся в этом скрипте обработчике отслеживания существования держать ссылки на все скрипты где он используется, что ещё хуже.
DrMort
UNец
 
Сообщения: 28
Зарегистрирован: 08 фев 2013, 08:35

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение 1max1 23 окт 2019, 11:58

А вот это нельзя использовать https://docs.unity3d.com/ScriptReferenc ... rStay.html? Обязательно листы хранить?
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение DrMort 23 окт 2019, 12:05

Конкретно при использовании в триггере это может и поможет, но это был лишь пример. Например у одного GameObject может быть несколько коллайдеров, а обработать нужно только один раз на GameObject.
Подобная ситуация может быть в любом другом месте, в котором используется список GameObject и где нужно контролировать а живы ли они ещё.
DrMort
UNец
 
Сообщения: 28
Зарегистрирован: 08 фев 2013, 08:35

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение 1max1 23 окт 2019, 12:21

но память не резиновая - GC её не освободит

Это было от балды сказано или ты всё же проверял? Сборщик собирает все объекты на которых нет ссылок, соответственно если ты удалишь из списка свой объект, то со временем его соберут.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение DrMort 23 окт 2019, 12:28

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

goList.RemoveAll(item => item == null);
DrMort
UNец
 
Сообщения: 28
Зарегистрирован: 08 фев 2013, 08:35

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение DrMort 23 окт 2019, 12:33

В любом случае увы, но это не отвечает на вопрос как отследить удаление GameObject
DrMort
UNец
 
Сообщения: 28
Зарегистрирован: 08 фев 2013, 08:35

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение Tolking 23 окт 2019, 12:42

Сами по себе объекты не удаляются... Там где объект удаляешь - сообщай об этом...
Ковчег построил любитель, профессионалы построили Титаник.
Аватара пользователя
Tolking
Адепт
 
Сообщения: 2714
Зарегистрирован: 08 июн 2009, 18:22
Откуда: Тула

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение DrMort 23 окт 2019, 12:51

Вот про то и речь, что события OnDestroy для GameObject не существует, по крайней мере я о нём не знаю, то есть нужно писать собственный класс для отслеживания.
DrMort
UNец
 
Сообщения: 28
Зарегистрирован: 08 фев 2013, 08:35

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение 1max1 23 окт 2019, 13:14

DrMort писал(а):Вот про то и речь, что события OnDestroy для GameObject не существует, по крайней мере я о нём не знаю, то есть нужно писать собственный класс для отслеживания.

А зачем тебе OnDestroy? Ты же в коде где-то вызываешь Destroy(go), вот в том месте и делай все необходимое.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение DrMort 23 окт 2019, 13:58

Да, всё сводится к тому что нужно писать свой менеджер удаления объектов.
DrMort
UNец
 
Сообщения: 28
Зарегистрирован: 08 фев 2013, 08:35

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение Friend123 23 окт 2019, 14:14

DrMort писал(а):Да, всё сводится к тому что нужно писать свой менеджер удаления объектов.

Нафига так усложнять? Может стоит пересмотреть пути решения задачи? Например, написать некий менеджер, который будет этим листом управлять, он же будет удалять объекты физически со сцены и удалять их из листа.
Аватара пользователя
Friend123
Старожил
 
Сообщения: 701
Зарегистрирован: 26 фев 2012, 22:12
Откуда: Тверь
  • ICQ

Re: NULL который не NULL или как подписаться на GameObject.OnDes

Сообщение DrMort 23 окт 2019, 16:36

А если листов пять? Восемь?
Я пришёл к выводу что нужно удалять объекты посредством своего класса, который уже по подписке будет уведомлять всех "заинтересованных".
DrMort
UNец
 
Сообщения: 28
Зарегистрирован: 08 фев 2013, 08:35


Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3