protected void _makeShot(TInstantiationCommand command)
    {
        BaseGunConfig gunConfigs = command.mGunConfigs;

        /// create a new instance of a bullet prefab
        GameObject bulletInstance = GameObject.Instantiate(gunConfigs.mBulletPrefab, command.mGunPosition, Quaternion.identity, mBulletsRootTransform);

        BulletComponent bulletComponent = bulletInstance.GetComponent <BulletComponent>();

        bulletComponent.mDamage         = gunConfigs.mDamage;
        bulletComponent.mSpeed          = gunConfigs.mBulletSpeed;
        bulletComponent.mTargetPosition = command.mEnemyTargetPosition;
    }
    protected void _processSingleTurret(GunComponent gun, ComponentGroupArray <TEnemyGroup> enemies)
    {
        Transform gunTransform = gun.CachedTransform;

        BaseGunConfig gunConfigs = gun.mConfigs;

        /// this method can return null if there are no enemies within an attack zone
        EnemyComponent nearestEnemy = _getNearestEnemy(gunTransform, gunConfigs.mRadius, enemies);

        /// skip other logic if there are no enemies near the turret
        if (nearestEnemy == null)
        {
            return;
        }

        Transform enemyTransform = nearestEnemy.CachedTransform;

        /// rotate the turret towards a target
        gunTransform.rotation = QuaternionUtils.LookRotationXZ(enemyTransform.position - gunTransform.position);

        /// shooting logic
        if (gun.mElapsedReloadingTime > gunConfigs.mReloadInterval)
        {
            /// create a deffered request for instantiation of a new bullet
            mInstantiationBuffer.Add(new TInstantiationCommand {
                mGunPosition = gun.mBulletSpawTransform.position, mGunConfigs = gunConfigs, mEnemyTargetPosition = enemyTransform.position
            });

            gun.mElapsedReloadingTime = 0.0f;             // starts to wait for an end of a reloading cycle

            return;
        }

        /// wait for a gun is being reloading
        gun.mElapsedReloadingTime += Time.deltaTime;
    }