Skip to content

Instantly share code, notes, and snippets.

@quabug
Created April 14, 2019 09:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save quabug/9668699c43dc90c5a555e5f144291a85 to your computer and use it in GitHub Desktop.
Save quabug/9668699c43dc90c5a555e5f144291a85 to your computer and use it in GitHub Desktop.
Create Unity ECS systems by zenject way which automaticly inject necessary instances into constructor of system.
class MainInstaller : MonoInstaller<MainInstaller>
{
public override void InstallBindings() {
Container.BindInstance(World.Active);
Container.Bind<WorldSystemCreatorFactory>().AsSingle().WithArguments(Container);
Container.Bind<SomeService>().ToSelf().AsSingle();
Container.Bind<Example>().ToSelf().AsSingle().NonLazy();
}
}
class SomeService {}
class SomeSystem : ComponentSystem
{
public SomeSystem(SomeService service) {}
protected override void OnUpdate() {}
}
class Example
{
public Example(WorldSystemCreatorFactory creatorFactory, World world) {
var creator = creatorFactory(world);
var someSystem = creator(typeof(SomeSystem));
}
}
#if !DISABLE_ZENJECT
using System;
using Unity.Entities;
using Zenject;
using Zenject.Internal;
namespace FortyTwo
{
public class WorldSystemCreatorFactory
{
private readonly DiContainer _container;
public WorldSystemCreatorFactory(DiContainer container)
{
_container = container;
}
public Func<Type, ComponentSystemBase> MakeCreator(World world)
{
var subContainer = _container.CreateSubContainer();
subContainer.BindInstance(world);
subContainer.BindInstance(world.EntityManager);
return systemType =>
{
var typeInfo = TypeAnalyzer.GetInfo(systemType);
var paramValues = ZenPools.SpawnArray<object>(typeInfo.InjectConstructor.Parameters.Length);
var extraArgs = ListPool<TypeValuePair>.Instance.Spawn();
var concreteType = systemType;
var context = new InjectContext(subContainer, concreteType, null);
try
{
for (int i = 0; i < typeInfo.InjectConstructor.Parameters.Length; i++)
{
var injectInfo = typeInfo.InjectConstructor.Parameters[i];
if (!InjectUtil.PopValueWithType(
extraArgs, injectInfo.MemberType, out var value))
{
using (var subContext = ZenPools.SpawnInjectContext(
subContainer, injectInfo, context, null, concreteType, null))
{
value = subContainer.Resolve(subContext);
}
}
paramValues[i] = value;
}
return world.CreateSystem(systemType, paramValues);
}
finally
{
ListPool<TypeValuePair>.Instance.Despawn(extraArgs);
ZenPools.DespawnArray(paramValues);
}
};
}
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment