Zenject ломает сборку под WebGL
Представьте, что вы делаете проект на Unity3D.
И вот вы решаете облегчить себе жизнь и использовать DI контейнер.
Для этого обычно все используют Zenject.
Но что делать если Zenject ломает функциональность на сборках под WebGL.
Введение
Zenject — контейнер внедрения зависимостей с открытым исходным кодом.
Zenject можно применять и для С# приложений, разработанных без Unity3D.
Этот контейнер довольно популярен среди Unity разработчиков.
Zenject довольно прост и удобен в использовании. Но с ним надо быть очень осторожным и внимательным. Так как в случае ошибок, найти причину бывает не просто.
Проблема
В Zenject есть два типа контекста.
Scene Context - создается для каждой сцены отдельно.
Project Context - создается автоматически для всего проекта. Существует в единственном экземпляре.
Предположим вы хотите чтобы какие объекты были в игре в единственном экземпляре и не удалялись при смене сцен.
Это может понадобится, например, для фоновой музыки или общих UI элементов.
Для этого логичнее всего сделать префаб с необходимым объектом и потом его создать в проекте примерно следующим кодом.
Этот код должен быть привязан к Project Context Zenject.
namespace App.Installers
{
public class AppInstaller : MonoInstaller
{
[SerializeField] private MainController mainController;
[SerializeField] private MusicController musicController;
public override void InstallBindings()
{
BindMainController();
BindMusicController();
}
private void BindMainController()
{
Container.Bind<MainController>()
.FromComponentInNewPrefab(mainController)
.WithGameObjectName("MainCanvas")
.AsSingle()
.NonLazy();
}
private void BindMusicController()
{
Container.Bind<MusicController>()
.FromComponentInNewPrefab(musicController)
.WithGameObjectName("Music")
.AsSingle()
.NonLazy();
}
}
}
После этого на сцене появятся объекты в блоке DontDestroyOnLoad
Все вроде хорошо и в редакторе все будет работать отлично.
Но при сборке под WebGL ваше приложение будет работать не так как вы задумывали.
Фоновая музыка играть не будет. Общие окна с ошибками и тд отображаться не будут.
Поиск в интернете результата не дал.
Но с помощью отладки я понял что наши неубиваемые объекты при смене сцен все равно удаляются.
Решение
Так что же делать чтобы объекты не удалялись со сцен.
Можно пойти простым способом добавить на эти объекты скрипты и прописать там следующий код.
namespace App.Controllers
{
public class MusicController : MonoBehaviour
{
private void Awake()
{
DontDestroyOnLoad(gameObject);
}
}
}
Но это не удобно, так как придется всегда помнить об этом и писать дополнительный код.
Как оказалось решением является установка одного флага в настройке Project Context Zenject.
Это свойство называетяс Parent New Objects Under Context
Проставив этот флаг, наши объекты немного поменяют иерархию и она будет выглядеть следующим образом.
После этого наша сборка под WebGL начинает работать как задумано.
Вот такое простое, но не очевидное решение.