// MIT License - Copyright (c) 2025 wallstop
// Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE
namespace Samples.UnityHelpers.DI.Zenject
{
using global::Zenject;
using UnityEngine;
using WallstopStudios.UnityHelpers.Integrations.Zenject;
public sealed class SpawnerZenject : MonoBehaviour
{
[SerializeField]
private RelationalConsumer _componentPrefab;
[SerializeField]
private GameObject _hierarchyPrefab;
[SerializeField]
private Transform _defaultParent;
[Inject]
private DiContainer _container;
[Inject(Optional = true)]
private RelationalConsumerPool _pool;
///
/// Instantiate a component prefab through Zenject so dependencies and relational fields are populated automatically.
///
public RelationalConsumer SpawnComponent(Transform parent)
{
Transform targetParent = parent != null ? parent : _defaultParent;
return _container.InstantiateComponentWithRelations(_componentPrefab, targetParent);
}
///
/// Instantiate a hierarchy prefab and hydrate every attributed component beneath it.
///
public GameObject SpawnHierarchy(Transform parent)
{
Transform targetParent = parent != null ? parent : _defaultParent;
return _container.InstantiateGameObjectWithRelations(
_hierarchyPrefab,
targetParent,
includeInactiveChildren: true
);
}
///
/// Rent an instance from a Zenject memory pool (falls back to SpawnComponent when the pool is not bound).
///
public RelationalConsumer SpawnFromPool(Transform parent)
{
if (_pool == null)
{
return SpawnComponent(parent);
}
RelationalConsumer instance = _pool.Spawn();
Transform targetParent = parent != null ? parent : _defaultParent;
if (targetParent != null)
{
instance.transform.SetParent(targetParent, false);
}
return instance;
}
///
/// Return an instance to the pool.
///
public void DespawnToPool(RelationalConsumer instance)
{
if (_pool == null || instance == null)
{
return;
}
_pool.Despawn(instance);
}
///
/// Hydrate an existing hierarchy that was created outside of the container (editor tooling etc.).
///
public void HydrateExistingHierarchy(GameObject root)
{
if (root == null)
{
return;
}
_container.AssignRelationalHierarchy(root, includeInactiveChildren: true);
}
}
}