private void UpdateCannonAim()
        {
            Vector3?targetPosition = null;

            RaycastHit straightHit;

            if (Physics.Raycast(targetDetectorOrigin.position, targetDetectorOrigin.forward, out straightHit, ~targetDetectionLayersToIgnore))
            {
                if (enemyLayerMask.ContainsLayer(straightHit.collider.gameObject.layer))
                {
                    targetPosition = straightHit.transform.position;
                }
            }

            if (!targetPosition.HasValue)
            {
                var hits =
                    PhysicsExtensions.RaycastCilinderWithEightRays(
                        targetDetectorOrigin.position,
                        targetDetectorOrigin.position + targetDetectorOrigin.forward * 10f,
                        targetDetectionRadius,
                        ~targetDetectionLayersToIgnore,
                        debugTargetDetection,
                        debugTargetDetection
                        );

                foreach (var hit in hits)
                {
                    if (enemyLayerMask.ContainsLayer(hit.collider.gameObject.layer))
                    {
                        if (debugTargetDetection)
                        {
                            Debug.DrawLine(targetDetectorOrigin.position, hit.point, Color.red);
                        }

                        targetPosition = hit.transform.position;
                        break;
                    }
                }
            }

            if (targetPosition.HasValue)
            {
                AimCannonsToPosition(targetPosition.Value);
                enemyOnTarget = true;

                if (debugTargetDetection)
                {
                    Debug.DrawLine(targetDetectorOrigin.position, targetPosition.Value, Color.red);
                }
            }
            else
            {
                AimCannonsForward();
                enemyOnTarget = false;
            }

            crosshair.color = currentCrosshairColor;
            primaryWeaponLeftCannonAttachment.transform.rotation    = currentPrimaryWeaponLeftCannonRotation;
            primaryWeaponRightCannonAttachment.transform.rotation   = currentPrimaryWeaponRightCannonRotation;
            secondaryWeaponLeftCannonAttachment.transform.rotation  = currentSecondaryWeaponLeftCannonRotation;
            secondaryWeaponRightCannonAttachment.transform.rotation = currentSecondaryWeaponRightCannonRotation;
        }
        protected bool IsPositionDirectlyReachable(Vector3 targetPosition)
        {
            var sqrMagnitudeToPosition = (targetPosition - transform.position).sqrMagnitude;

            // First, check for straight line of sight, from center to center.
            RaycastHit hit;

            if (Physics.Raycast(transform.position, targetPosition - transform.position, out hit, float.MaxValue, ~layersToIgnoreInSightTest))
            {
                var sqrMagnitudeToHit = (hit.point - transform.position).sqrMagnitude;

                // If the hit point is closer than the position that we want to see, there is something in between.
                if (sqrMagnitudeToHit < sqrMagnitudeToPosition)
                {
                    Debug.DrawLine(transform.position, hit.point);
                    return(false);
                }
            }

            // Now we check if the boundaries of the object are also directly reachable to destination point.
            var hits =
                PhysicsExtensions.RaycastCilinderWithEightRays(
                    transform.position,
                    targetPosition,
                    sightTestSphereCastRadius,
                    ~layersToIgnoreInSightTest,
                    debugReachabilityTest
                    );

            var obstructed = false;

            foreach (var h in hits)
            {
                var sqrMagnitudeToHit = (h.point - transform.position).sqrMagnitude;

                // If the hit point is closer than the position that we want to see, there is something in between.
                if (sqrMagnitudeToHit < sqrMagnitudeToPosition)
                {
                    obstructed = true;
                    break;
                }
            }

            return(!obstructed);

            //var origins = new Vector3[8];
            //origins[0] = transform.TransformPoint(Vector3.up * sightTestSphereCastRadius);
            //origins[1] = transform.TransformPoint((Vector3.up + Vector3.right).normalized * sightTestSphereCastRadius);
            //origins[2] = transform.TransformPoint(Vector3.right * sightTestSphereCastRadius);
            //origins[3] = transform.TransformPoint((Vector3.down + Vector3.right).normalized * sightTestSphereCastRadius);
            //origins[4] = transform.TransformPoint(Vector3.down * sightTestSphereCastRadius);
            //origins[5] = transform.TransformPoint((Vector3.down + Vector3.left).normalized * sightTestSphereCastRadius);
            //origins[6] = transform.TransformPoint(Vector3.left * sightTestSphereCastRadius);
            //origins[7] = transform.TransformPoint((Vector3.up + Vector3.left).normalized * sightTestSphereCastRadius);

            //var direction = targetPosition - transform.position;
            //var sqrMagnitudeToPosition = (targetPosition - transform.position).sqrMagnitude;

            //RaycastHit hit;
            //foreach (var origin in origins)
            //{
            //    if (Physics.Raycast(origin, direction, out hit, float.MaxValue, ~layersToIgnoreInSightTest))
            //    {
            //        if (debugReachabilityTest)
            //        {
            //            Debug.DrawLine(origin, hit.point);
            //        }

            //        var sqrMagnitudeToHit = (hit.point - transform.position).sqrMagnitude;

            //        // If the hit point is closer than the position that we want to see, there is something in between.
            //        if (sqrMagnitudeToHit < sqrMagnitudeToPosition)
            //        {
            //            return false;
            //        }
            //    }
            //}

            //// If nothing was hit, there is nothing between the position and the observer.
            //return true;
        }