crosshairsProjectile

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., Projectile script).

  • Model Visual representation of the projectile (bullet, rocket, etc.). Typically a mesh or 3D model.

  • Trail Empty GameObject holding the TrailRenderer component 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 TrailRenderer is cleared to avoid visual artifacts

Dependency Injection (Zenject)

The projectile receives all required dependencies via Zenject:

  • ProjectileConfig — contains movement and collision parameters

  • IPlayerContext — provides player damage data

  • ILogService — optional logging service

  • Camera (MainCamera) — used for visibility checks

Movement and Lifetime

Projectile movement is processed in FixedUpdate:

  • Move() — moves the projectile forward using the configured speed

  • CheckFlyTime() — 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 OverlapSphereNonAlloc check is used for close-range edge cases

  • Only 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 IHealth

  • the 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

The 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

To create a Projectile, you should pay attention to two components:

  • the IGameFactory interface

  • the GameFactory class

  1. The IGameFactory interface defines the method signature for creating a Projectile instance:

  1. The GameFactory class provides the implementation of the CreateProjectile method. Object creation is performed using IInstantiator, which ensures that all Zenject dependencies are properly injected.

  1. 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 OnReturned event 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.

  1. In the GameplayBootstrapState class, where all pools are initialized, the Projectile pool 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.

circle-info

For more details, click here.

Last updated