Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing Boiler Plate for Spawning Prefabs. #78

Open
SimonNordon4 opened this issue Apr 10, 2023 · 0 comments
Open

Removing Boiler Plate for Spawning Prefabs. #78

SimonNordon4 opened this issue Apr 10, 2023 · 0 comments

Comments

@SimonNordon4
Copy link

Right now it's a lot of setup to just spawn a prefab.

The class looks like this:

public class Before : MonoBehaviour, IPoolable<IMemoryPool>, IDisposable
        {
            private IMemoryPool _pool;
            
            public void OnDespawned()
            {
                _pool = null;
            }

            public void OnSpawned(IMemoryPool p1)
            {
                _pool = p1;
            }

            public void Dispose()
            {
                _pool.Despawn(this);
            }
            
            public class Factory : PlaceholderFactory<Before>
            { }
            public class Pool : MonoPoolableMemoryPool<IMemoryPool, Before>
            { }
        }

        public class AfterInstaller : MonoInstaller
        {
            public After prefab;
            
            public override void InstallBindings()
            {
                Extensions.BindPoolable<After>(Container,
                    c => c.WithInitialSize(5)
                        .FromComponentInNewPrefab(prefab)
                        .UnderTransformGroup("After")
                        .AsCached());
            }
        }
        
        public class After : PoolableMonoBehaviour<After>
        {
      
        }

and the binding looks like this

        public class BeforeInstaller : MonoInstaller
        {
            public Before prefab;
            
            public override void InstallBindings()
            {
                Container.BindFactory<Before, Before.Factory>()
                    .FromPoolableMemoryPool<Before, Before.Pool>(pool => pool
                        .WithInitialSize(5)
                        .FromComponentInNewPrefab(prefab)
                        .UnderTransformGroup("Before")
                        .AsCached());
            }
        }

I wrote a wrapper class for this kind of thing.

        public abstract class PoolableMonoBehaviour<T> : MonoBehaviour, IPoolable<IMemoryPool>, IDisposable where T : PoolableMonoBehaviour<T>
        {
            protected IMemoryPool _pool;

            public void OnSpawned(IMemoryPool pool)
            {
                _pool = pool;
                OnSpawnedInternal();
            }

            public virtual void OnSpawnedInternal()
            {
                
            }

            public void OnDespawned()
            {
                OnDespawnedInternal();
            }

            public virtual void OnDespawnedInternal()
            {
                
            }
            

            public virtual void Dispose() => _pool.Despawn(this);
            
            public class Factory : PlaceholderFactory<T>
            { }
            
            public class Pool : MonoPoolableMemoryPool<IMemoryPool, T>
            { }
        }

Right now it doesn't support parameters, but that would be easy to do, just duplicate the class and add TParam infront of Every IMermoryPool.

I also wrote an extension method for binding

namespace Zenject.Extensions  
{
    public static class Extensions
    {
        public static ArgConditionCopyNonLazyBinder BindPoolable<TPoolable>
            (DiContainer container,Action<MemoryPoolInitialSizeMaxSizeBinder<TPoolable>> poolBinder)
        where TPoolable : PoolableMonoBehaviour<TPoolable>
        {
            var x = container
                .BindFactory<TPoolable, PoolableMonoBehaviour<TPoolable>.Factory>()
                .FromPoolableMemoryPool<TPoolable, PoolableMonoBehaviour<TPoolable>.Pool>
                    (poolBinder);
            return x;
        }
    }
}

With these new scripts, the code goes from looking like it did at the top to this:

        public class AfterInstaller : MonoInstaller
        {
            public After prefab;
            
            public override void InstallBindings()
            {
                Extensions.BindPoolable<After>(Container,
                    c => c.WithInitialSize(5)
                        .FromComponentInNewPrefab(prefab)
                        .UnderTransformGroup("After")
                        .AsCached());
            }
        }
        
        public class After : PoolableMonoBehaviour<After>
        {
      
        }

This makes it mech easier to for a gameobject to return itself to the pool

        public class After : PoolableMonoBehaviour<After>
        {
            private float lifetime = 1f;
            public override void OnSpawnedInternal()
            {
                lifetime = 1f;
            }
            
            private void Update()
            {
                lifetime -= Time.deltaTime;
                if (lifetime <= 0)
                {
                    Dispose();
                }
            }
        }

This isn't really an issue, just now that Extenject isn't being supported I thought it would be useful for people trying to wrap their heads around prefab spawning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant