using UnityEngine; using Zenject; using FlappyBird.Core; using FlappyBird.Gameplay; using FlappyBird.Gameplay.Bird; using FlappyBird.Gameplay.Pipes; namespace FlappyBird.Installers { /// /// Zenject MonoInstaller for core gameplay bindings. /// Attach this to the SceneContext GameObject in each gameplay scene. /// public sealed class GameInstaller : MonoInstaller { [Header("Game Management")] [Tooltip("GameManagerView MonoBehaviour in the scene.")] [SerializeField] private GameManagerView _gameManagerView; [Tooltip("BirdCollisionView MonoBehaviour on the bird GameObject.")] [SerializeField] private BirdCollisionView _birdCollisionView; [Header("Bird")] [Tooltip("Drag the Bird GameObject here (must have Rigidbody2D).")] [SerializeField] private BirdView _birdView; [Tooltip("BirdSettings ScriptableObject asset.")] [SerializeField] private BirdSettings _birdSettings; [Header("Pipes")] [Tooltip("PipeSettings ScriptableObject asset.")] [SerializeField] private PipeSettings _pipeSettings; [Tooltip("Pipe-pair prefab with a PipeView component.")] [SerializeField] private PipeView _pipePrefab; [Tooltip("PipeSpawnerTicker MonoBehaviour in the scene.")] [SerializeField] private PipeSpawnerTicker _pipeSpawnerTicker; public override void InstallBindings() { BindGameState(); BindScore(); BindBird(); BindPipes(); BindDeath(); } // ── Game State ───────────────────────────────────────────────────── private void BindGameState() { Container.Bind() .To() .AsSingle(); // Bind the concrete MonoBehaviour so BirdCollisionView can resolve it by type. Container.Bind() .FromInstance(_gameManagerView) .AsSingle(); Container.QueueForInject(_gameManagerView); Container.QueueForInject(_birdCollisionView); } // ── Score ────────────────────────────────────────────────────────── private void BindScore() { Container.Bind() .To() .AsSingle(); } // ── Bird ─────────────────────────────────────────────────────────── private void BindBird() { Container.Bind() .FromComponentOn(_birdView.gameObject) .AsSingle(); Container.BindInstance(_birdSettings).AsSingle(); Container.Bind() .To() .AsSingle(); Container.QueueForInject(_birdView); } // ── Pipes ────────────────────────────────────────────────────────── private void BindPipes() { Container.BindInstance(_pipeSettings).AsSingle(); Container.BindFactory() .FromComponentInNewPrefab(_pipePrefab) .AsSingle(); Container.BindInterfacesTo() .AsSingle(); Container.Bind() .To() .AsSingle(); Container.QueueForInject(_pipeSpawnerTicker); } // ── Death ────────────────────────────────────────────────────────── private void BindDeath() { // BindInterfacesTo registers the same instance for both // IDeathHandler and IInitializable (so Zenject calls Initialize()). Container.BindInterfacesTo() .AsSingle(); } } }