Страница 1 из 1

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

СообщениеДобавлено: 23 окт 2019, 11:18
DrMort
Затравка. Есть у нас 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()?

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

СообщениеДобавлено: 23 окт 2019, 11:34
Xtir
Синтаксис:
Используется 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);
    }
}


Можно сделать что-то типа такого. Когда объект попадает в триггер, он записывает к себе этот триггер(соответсвенно триггер добавляет этот объект в список к себе), а когда уничтожается вызывает метод триггера который удалит его из списка объектов которые находятся в триггере.

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

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

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

СообщениеДобавлено: 23 окт 2019, 11:58
1max1
А вот это нельзя использовать https://docs.unity3d.com/ScriptReferenc ... rStay.html? Обязательно листы хранить?

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

СообщениеДобавлено: 23 окт 2019, 12:05
DrMort
Конкретно при использовании в триггере это может и поможет, но это был лишь пример. Например у одного GameObject может быть несколько коллайдеров, а обработать нужно только один раз на GameObject.
Подобная ситуация может быть в любом другом месте, в котором используется список GameObject и где нужно контролировать а живы ли они ещё.

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

СообщениеДобавлено: 23 окт 2019, 12:21
1max1
но память не резиновая - GC её не освободит

Это было от балды сказано или ты всё же проверял? Сборщик собирает все объекты на которых нет ссылок, соответственно если ты удалишь из списка свой объект, то со временем его соберут.

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

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

goList.RemoveAll(item => item == null);

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

СообщениеДобавлено: 23 окт 2019, 12:33
DrMort
В любом случае увы, но это не отвечает на вопрос как отследить удаление GameObject

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

СообщениеДобавлено: 23 окт 2019, 12:42
Tolking
Сами по себе объекты не удаляются... Там где объект удаляешь - сообщай об этом...

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

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

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

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

А зачем тебе OnDestroy? Ты же в коде где-то вызываешь Destroy(go), вот в том месте и делай все необходимое.

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

СообщениеДобавлено: 23 окт 2019, 13:58
DrMort
Да, всё сводится к тому что нужно писать свой менеджер удаления объектов.

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

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

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

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

СообщениеДобавлено: 23 окт 2019, 16:36
DrMort
А если листов пять? Восемь?
Я пришёл к выводу что нужно удалять объекты посредством своего класса, который уже по подписке будет уведомлять всех "заинтересованных".