Projectile
Overview
This section provides a detailed overview of the implementation of the Projectile logic, including:
Projectile prefab structure
script responsible for Projectile behavior
usage of factories for spawning Projectile instances
integration with the object pooling system
configuration file management
Projectile Prefab Structure
Projectile (Empty GameObject)
├── Model (Mesh)
└── Trail (Empty GameObject with TrailRenderer)Object Descriptions
Projectile Root GameObject containing the main logic and scripts (e.g.,
Projectilescript).Model Visual representation of the projectile (bullet, rocket, etc.). Typically a mesh or 3D model.
Trail Empty GameObject holding the
TrailRenderercomponent that creates the visual trail effect behind the projectile during flight.

Script responsible for Projectile behavior (Projectile.cs)
The Projectile script defines the full lifecycle and behavior of a projectile instance.
It is designed to work with Zenject dependency injection and an object pooling system.
Responsibilities
The Projectile component is responsible for:
handling projectile movement and lifetime
detecting collisions with enemies
applying damage to valid targets
checking visibility within the camera view
returning the projectile back to the pool
visual cleanup and state reset between reuse
Initialization
Before being fired, the projectile must be initialized using the Initialize method.
During initialization:
the flight direction is taken from the fire point
position and rotation are reset
internal state is cleared (
flyTime,returned,previousPosition)the
TrailRendereris cleared to avoid visual artifacts
Dependency Injection (Zenject)
The projectile receives all required dependencies via Zenject:
ProjectileConfig— contains movement and collision parametersIPlayerContext— provides player damage dataILogService— optional logging serviceCamera(MainCamera) — used for visibility checks
Movement and Lifetime
Projectile movement is processed in FixedUpdate:
Move()— moves the projectile forward using the configured speedCheckFlyTime()— returns the projectile to the pool once its lifetime expires
Collision Detection
Collision detection is performed using SphereCast to prevent missed hits at high speeds.
A sphere cast is executed between the previous and current positions
A fallback
OverlapSphereNonAlloccheck is used for close-range edge casesOnly objects on the Enemy layer are considered
This approach avoids per-frame memory allocations and ensures reliable hit detection.
Attack Handling
When a valid target is detected:
the target must implement
IHealththe target must be visible within the camera viewport
damage is applied using the player’s current stats
the projectile is immediately returned to the pool
Visibility Check
To prevent off-screen hits, the projectile verifies that the target is visible by converting its world position to viewport coordinates.
Only targets inside the camera view are considered valid.
Creating Projectile Using a Factory
Projectile Using a FactoryThe Projectile class requires Zenject to resolve its dependencies, therefore instances of the Projectile prefab must be created via a factory using Zenject methods (InstantiatePrefab).
Spawning Projectile via a Factory
Projectile via a FactoryTo create a Projectile, you should pay attention to two components:
the
IGameFactoryinterfacethe
GameFactoryclass
The
IGameFactoryinterface defines the method signature for creating aProjectileinstance:
The
GameFactoryclass provides the implementation of theCreateProjectilemethod. Object creation is performed usingIInstantiator, which ensures that all Zenject dependencies are properly injected.
The Projectile prefab is registered in the corresponding pool configuration.

Pooling Integration
Projectile implements the IPoolReturnable<Projectile> interface, allowing it to be reused via an object pool.
The
OnReturnedevent notifies the pool manager when the projectile should be recycled.The
ReturnToPool()method ensures that the projectile is returned only once.
Connecting the Factory with the Pool
The pool must be informed how to create objects of type Projectile.
For this purpose, a call to the CreateProjectile() method is added to the Create() method of the ObjectFactory class.
In the
GameplayBootstrapStateclass, where all pools are initialized, theProjectilepool initialization has been added.
3. To obtain a projectile instance from the pool, use:
After usage, projectiles return to the pool automatically via the ReturnToPool() method inside the Projectile class.
Configuration file management
Projectile parameters such as flight speed, flight time, and collision radius are set via the ScriptableObject configuration asset: SO_ProjectileConfig

This allows easy tweaking of projectile behavior without modifying code.
To make Zenject aware of this config, it is registered in SO_CoreConfig via ConfigsInstaller.

For more details, click here.
Last updated