Open waitxd opened 5 years ago
Spent some time to solve this problem.
Right now in Extenject each of MonoMemoryPool<TParam1..TParam5,TContract>
(one till five parameters) classes is using MemoryPoolBase<TContract>
with only one parameter, which holds IFactory<TContract>
(no parameters in Create method). So there is no way to pass additional parameters to the factrory. This might be a good place for further improvements.
However, I came to the conclusion that the idea of using MonoMemoryPool
with Prefab[Resource]Factory
is broken by design. If you pass different prefabs to the MonoMemoryPool.Spawn
, the pool will contain different prefabs after MonoMemoryPool.Despawn
. This can lead to the undefined behaviour when someone will reuse them.
But if someone really need to pass parameters from memory pool to underlaying factory you can use something like that.
Yep, that all makes sense. You can't use the same memory pool to share instances that are created using multiple different prefabs. One issue I see with your solution is that using code could pass different prefabs. Which might not be an issue if you're injecting it AsTransient
but worth pointing out. Another solution would be to use a dictionary like this:
public class BulletFactory
{
readonly Dictionary<GameObject, IMemoryPool<Bullet>> _pools =
new Dictionary<GameObject, IMemoryPool<Bullet>>();
readonly DiContainer _container;
readonly MemoryPoolSettings _settings;
public BulletFactory(DiContainer container, MemoryPoolSettings settings)
{
_container = container;
_settings = settings;
}
public void Despawn(GameObject prefab, Bullet bullet)
{
_pools[prefab].Despawn(bullet);
}
public Bullet Spawn(GameObject prefab)
{
IMemoryPool<Bullet> pool;
if (!_pools.TryGetValue(prefab, out pool))
{
pool = _container.Instantiate<MonoMemoryPool<Bullet>>(
new object[] { _settings, new FuncFactory<Bullet>(() => _container.InstantiatePrefabForComponent<Bullet>(prefab))});
_pools.Add(prefab, pool);
}
return pool.Spawn();
}
}
public class FuncFactory<T> : IFactory<T>
{
readonly Func<T> _factoryMethod;
public FuncFactory(Func<T> factoryMethod)
{
_factoryMethod = factoryMethod;
}
public T Create()
{
return _factoryMethod();
}
}
@svermeulen Hi , Can you explain how to use BulletFactory ? I can not use BindFactory<Bullet, BulletFactory> because BulletFactory is not inherit from PlaceholdFactory?
In current implementation it seems impossible to create MonoMemoryPool and provide the prefab to use for the new object (like with PrefabResourceFactory or PrefabFactory). Even when you are instantiating memory pool directly.