https://syjgin.itch.io/through-the-clouds/devlog/827915/v083-peaceful-airships-added-tutorial-and-ui-renew На прошлых выходных всё-таки доделали версию 0.8.3, но благодаря багрепортам бдительных подписчиков уже насобирали исправлений на хотфикс, который выпустим в ближайшее время.
Параллельно с этим занимаемся механикой предыстории капитана, которая сможет влиять на сюжет.
А ещё параллельно занимаюсь большой правкой, которая должна исправить семейство багов, связанных с обращением к уже уничтоженному MonoBehaviour. Часть кода писалась, когда мой уровень владения C# и Unity был существенно хуже нынешнего, и теперь, похоже, пришло время рефакторинга.
Не встречал статей про ошибки такого типа именно применительно к Unity, поэтому, наверное, имеет смысл рассказать подробнее, может пригодиться кому-либо ещё.
Когда вы получаете откуда-то обычный объект C#, вы в целом безбоязненно можете подписаться на какие-то его события или присвоить его значение в качестве поля, главное — не забыть отписаться при уничтожении вашего объекта, чтобы избежать утечки памяти. Ну и в целом понимать, при каких обстоятельствах вы его можете обнулить, чтобы заранее убрать все ссылки на него, где они могут быть. Это достаточно просто, т.к. создание и уничтожение C# объектов находится под нашим контролем.
MonoBehaviour (объект скрипта Unity) в этом плане — куда более зыбкая почва. Я пробовал делать унаследованный от обычного List класс, который бы подписывался на событие удаления со сцены добавленных в него объектов, чтобы самоочиститься от невалидных ссылок, но это работало только иногда. Поэтому, в целом, я пришёл к тому, что попавший через коллайдер другой объект, который мы задетектили, нельзя добавлять напрямую в список видимых объектов, можно только забирать у него id, в за данными обращаться уже в централизованное хранилище, в котором все "живые" объекты обновляют свои данные, как только они поменялись (сейчас это работает по событиям типа изменения количества HP и отклонения более чем на 5 метров + 0.5 секунд от прошлых отправленных координат). И единственным источником данных о внешнем мире для UI игрока и логики NPC дирижаблей должна быть эта самая база данных того, что сейчас происходит в небе, а не сами объекты, которые могут в любой момент уничтожиться, если окажутся слишком далеко от игрока. Так как все данные лежат по своим словарям, это даже немного напоминает самопальную ECS:)
Проще говоря: если Unity объект является внешним по отношению к вашему скрипту логики, его нельзя заносить в поля, на его события нельзя подписываться