@ColdSpirit

Как избежать проблем с Execution Order?

Добрый день. Всякий раз, когда создаю на юнити более чем несколько связанных компонентов, возникают проблемы, что один компонент пытается работать с другим, еще не проинициализированным компонентом. Это доходит до абсурда - бывает, всё работает нормально, а после перезапуска сыпятся баги, ибо юнити поменял порядок создания компонентов, и всё теперь нужно перепроверять.

Сам знаю 2 метода решения этой проблемы:

1. Использовать Script Execution Order Settings. Считаю это ужасным костылем для тех, кто не умеет планировать архитектуру. Ибо добавлять, утрирую, каждый созданный компонент туда и настраивать ему порядок - это не дело.

2. Написать собственный менеджер компонентов, который будет вызывать Init() компонента в определенном порядке, описанном в самом компоненте, как альтернатива Start и Awake. Этот метод недалеко ушел от предыдущего, разве что он более гибкий (каждому компоненту можно написать своё время запуска), и более удобный в использовании. Тоже костыль.

Интересует, какие методы решения данной и подобных проблем существуют не только для юнити, но вообще в программировании?
Как вы решаете эту проблему, каких правил и приемов придерживаетесь?
  • Вопрос задан
  • 265 просмотров
Решения вопроса 3
lexxpavlov
@lexxpavlov
Программист, преподаватель
Я в Awake использую инициализацию самого компонента, не используя связи с другими компонентами. А в Start все компоненты уже инициализированы, их можно использовать.

Компонент A в Start получает ссылку на компонент B. Не факт, что B уже вызвал Start и не имеет нужные ссылки. Тут два варианта
- B тоже должен иметь ссылку на A. Тогда A может передать себя в B (до вызова B.Start).
- B должен иметь ссылку на компонент C. Тут могут быть проблемы.

Чтобы такие связи были независимы от порядка, то каждый компонент в Awake должен поместить себя (зарегистрироваться) в какой-то контейнер, через который в Start в любом компоненте можно получить нужную ссылку.

Контейнером может быть
- статическое поле класса (если компонент планируется только один, то получается типа полу-синглтон - поле устанавливается в Awake, а потом используется отовсюду во время Start и после)
- специальный список в родителе (если компонент не одиночка)
- IoC-контейнер
Ответ написан
flexer1992
@flexer1992
Unity Developer
Я бы не полагался на Script Execution Order а использовал бы что-то вроде этого: https://refactoring.guru/ru/design-patterns/chain-...
Ответ написан
Griboks
@Griboks Куратор тега C#
Используйте менеджер зависимостей, внедрения зависимостей. Пишите скрипты, в которых не может возникнуть подобных ошибок. Настраивайте зависимости в редакторе (скрипты) или в инспекторе.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы