Zenject (Unity) как передать сущность который наследуется от MonoBehaviour?
public sealed class GameInstaller : MonoInstaller
{
public override void InstallBindings()
{
this.Container
.Bind<Lavash>()
.FromNew()
.AsSingle();
}
}
public class Ingredient : MonoBehaviour
{
private Lavash select ; //этот класс наследуется от MonoBehaviour
[Inject]
public void Construct(Lavash _select)
{
select = _select;
}
}
Если убрать MonoBehaviour из класса "Lavash " то всё работает. Но мне он нужен.
Если не убрать, то такие ошибки:
1)
ZenjectException: Assert hit! Invalid type given during bind command. Expected type 'Lavash' to NOT derive from UnityEngine.Component
ModestTree.Assert.That (System.Boolean condition, System.String message, System.Object p1) (at Assets/Plugins/Zenject/Source/Internal/Assert.cs:347)
Zenject.BindingUtil.AssertIsNotComponent (System.Type type) (at Assets/Plugins/Zenject/Source/Binding/BindingUtil.cs:78)
Zenject.BindingUtil.AssertTypesAreNotComponents (System.Collections.Generic.IEnumerable`1[T] types) (at Assets/Plugins/Zenject/Source/Binding/BindingUtil.cs:117)
Zenject.FromBinder.FromNew () (at Assets/Plugins/Zenject/Source/Binding/Binders/FromBinders/FromBinder.cs:63)
GameInstaller.InstallBindings () (at Assets/Scripts/GameInstaller.cs:12)
Zenject.Context.InstallInstallers (System.Collections.Generic.List`1[T] normalInstallers, System.Collections.Generic.List`1[T] normalInstallerTypes, System.Collections.Generic.List`1[T] scriptableObjectInstallers, System.Collections.Generic.List`1[T] installers, System.Collections.Generic.List`1[T] installerPrefabs) (at Assets/Plugins/Zenject/Source/Install/Contexts/Context.cs:218)
Zenject.Context.InstallInstallers () (at Assets/Plugins/Zenject/Source/Install/Contexts/Context.cs:139)
Zenject.SceneContext.InstallBindings (System.Collections.Generic.List`1[T] injectableMonoBehaviours) (at Assets/Plugins/Zenject/Source/Install/Contexts/SceneContext.cs:346)
Zenject.SceneContext.Install () (at Assets/Plugins/Zenject/Source/Install/Contexts/SceneContext.cs:265)
Zenject.SceneContext.Validate () (at Assets/Plugins/Zenject/Source/Install/Contexts/SceneContext.cs:121)
Zenject.Internal.ZenUnityEditorUtil.ValidateCurrentSceneSetup () (at Assets/Plugins/Zenject/Source/Editor/ZenUnityEditorUtil.cs:67)
UnityEngine.Debug:LogException(Exception)
ModestTree.Log:ErrorException(Exception) (at Assets/Plugins/Zenject/Source/Internal/Log.cs:60)
Zenject.Internal.ZenUnityEditorUtil:ValidateCurrentSceneSetup() (at Assets/Plugins/Zenject/Source/Editor/ZenUnityEditorUtil.cs:72)
Zenject.Internal.ZenUnityEditorUtil:ValidateAllActiveScenes() (at Assets/Plugins/Zenject/Source/Editor/ZenUnityEditorUtil.cs:96)
Zenject.Internal.<>c:<ValidateAllActiveScenes>b__16_0() (at Assets/Plugins/Zenject/Source/Editor/ZenMenuItems.cs:262)
Zenject.Internal.ZenUnityEditorUtil:SaveThenRunPreserveSceneSetup(Action) (at Assets/Plugins/Zenject/Source/Editor/ZenUnityEditorUtil.cs:26)
Zenject.Internal.ZenMenuItems:ValidateAllActiveScenes() (at Assets/Plugins/Zenject/Source/Editor/ZenMenuItems.cs:260)
ZenjectException: Zenject Validation Failed! See errors below for details.
Zenject.Internal.ZenUnityEditorUtil.ValidateCurrentSceneSetup () (at Assets/Plugins/Zenject/Source/Editor/ZenUnityEditorUtil.cs:84)
Zenject.Internal.ZenUnityEditorUtil.ValidateAllActiveScenes () (at Assets/Plugins/Zenject/Source/Editor/ZenUnityEditorUtil.cs:96)
Zenject.Internal.ZenMenuItems+<>c.<ValidateAllActiveScenes>b__16_0 () (at Assets/Plugins/Zenject/Source/Editor/ZenMenuItems.cs:262)
Zenject.Internal.ZenUnityEditorUtil.SaveThenRunPreserveSceneSetup (System.Action action) (at Assets/Plugins/Zenject/Source/Editor/ZenUnityEditorUtil.cs:26)
UnityEngine.Debug:LogException(Exception)
ModestTree.Log:ErrorException(Exception) (at Assets/Plugins/Zenject/Source/Internal/Log.cs:60)
Zenject.Internal.ZenUnityEditorUtil:SaveThenRunPreserveSceneSetup(Action) (at Assets/Plugins/Zenject/Source/Editor/ZenUnityEditorUtil.cs:31)
Ответы (1 шт):
У MonoBehaviour
есть несколько особенностей: во-первых, MonoBehaviour
десериализуется Unity, а не создаётся с помощью конструктора; во-вторых, он не существует сам по себе, а идёт в связке с GameObject.
FromNew
в Zenject является вариантом по умолчанию, т.е. код
Container
.Bind<Lavash>()
.FromNew()
.AsSingle();
эквивалентен
Container
.Bind<Lavash>()
.AsSingle();
и создаёт он обычный объект класса через вызов его конструктора. Другими словами, для создания MonoBehaviour
он не пригоден.
Простейшим решением будет просто создать всё из кода, что делается так:
Container
.Bind<Lavash>()
.FromNewComponentOnNewGameObject()
.AsSingle();
Кроме того, если Ingredient
находится не в сцене, а тоже создаётся в Installer'е, то для него нужно будет вызвать NonLazy
Container
.Bind<Ingredient>()
.FromNewComponentOnNewGameObject()
.AsSingle()
.NonLazy();
так как Zenject по умолчанию не создаёт то, что нигде не используется.
Тем не менее, наиболее часто используют две другие опции, загрузку из префаба:
[SerializeField] Lavash _lavash;
public override void InstallBindings() {
Container
.Bind<Lavash>()
.FromComponentInNewPrefab(_lavash)
.AsSingle();
}
для чего нужно создать префаб Lavash, где будет присутствовать компонент Lavash, и задать этот префаб инсталлеру; или из ресурса:
public override void InstallBindings() {
Container
.Bind<Lavash>()
.FromComponentInNewPrefabResource("Lavash")
.AsSingle();
}
для чего префаб Lavash нужно поместить в папку Resources.
Это не единственные доступные опции. Более того, способов, которыми можно решить эту задачу, довольно много. Другие варианты можно найти, например, в Readme и в CheatSheet Zenject'а.