This site uses strictly necessary cookies. More Information

X- Home /

# Turret. Detect if target is inside horizontal and vertical arcs

Hi. I am trying to make a turret control for a spaceship (rts game). I have a coroutine that rotates the turret (a base horizontal axis, and a barrel vertical axis). It works fine, I have used Quaternion.Lookrotation and Quaternion.RotateTowards with a clamp to limit the minimum and maximum angle of both axes.

Then I have another coroutine that checks if there is a new target (the ship has two target lists: one holds ships added with right clicks (attack order), and the other adds ships when they are closer). If there is a target, it tells the first coroutine to target it.

To do this I need a function that returns a bool, depending on whether the target is within the turret arcs (both horizontal and vertical arcs). how can I do this? The arcs are relative to the ship and can go in all directions so it can tilt on all 3 axes.

The data I have is the transformation of the ship/horizontal turret, the position of the target, the minimum/maximum of both arcs.

I think it should make a projection of the target on the plane of the ship and? Can you guide me with this?

**Answer** by CodesCove
·
Jan 23 at 08:31 AM

I wrote this long time ago.. it's part of my sight sensor but should work for your case (no guarantee :) )

```
private bool IsInFOV(Transform fovTransform, UnityEngine.Vector3 targetPosition, float maxHorizontalDegrees, float maxVerticalDegrees)
{
//to local space
UnityEngine.Vector3 sourceDirectionForward = fovTransform.InverseTransformDirection(fovTransform.forward);
//to local space
UnityEngine.Vector3 targetLocalSpacePosition = fovTransform.InverseTransformPoint(targetPosition);
UnityEngine.Vector3 targetLocalSpaceXZDirection = new UnityEngine.Vector3(targetLocalSpacePosition.x, 0, targetLocalSpacePosition.z) - new UnityEngine.Vector3(0, 0, 0);
float targetLocalDistance = UnityEngine.Vector3.Distance(UnityEngine.Vector3.zero, targetLocalSpacePosition);
//this.distance = targetLocalDistance;
float targetAngleV = Mathf.Rad2Deg * (Mathf.Atan(Mathf.Abs(targetLocalSpacePosition.y) / Mathf.Abs(targetLocalDistance)));
float targetAngleH = UnityEngine.Vector3.Angle(targetLocalSpaceXZDirection, sourceDirectionForward);
if ((targetAngleV <= maxVerticalDegrees/2) && (targetAngleH <= maxHorizontalDegrees/2)) return true;
return false;
}
```

Hope you get it working,,

PS. here are parameter descriptions:

fovTransform = transform of the eye

targetPosition = position of the target

maxHorizontalDegrees = Maximum of horizontal (max 360) angle between eye and target in degrees

maxVerticalDegrees = Maximum of vertical (max 180) angle between eye and target in degrees

Thank you, it works perfect. Im only changed the final line, because i use a min/max for horizontal and a min/max for vertical. I used something like this:

```
return targetAngleH < maxHorizontalDegrees && targetAngleH > minHorizontalDegrees && targetAngleV < maxVerticalDegrees && targetAngleV > minVerticalDegrees;
```

**Answer** by diegonv
·
Jan 23 at 09:15 PM

If anyone is interested in how to rotate the turret, i use this (the objetive assignment is another topic).

turret_horizontal is the transform of the horizontal axis of the turret (the body).

turret_vertical is the transform of the vertical axis of the turret (the canon)

turret_vertical must be child of turret horizontal

void FixedUpdate() //or a coroutine with yield return new WaitForFixedUpdate { Quaternion _rot = Quaternion.LookRotation(targetTransform.position - turret_horizontal.position);

`turret_horizontal.rotation = Quaternion.RotateTowards(turret_horizontal.rotation, _rot, _vel_horizontal * Time.fixedDeltaTime); turret_horizontal.localEulerAngles = new Vector3(0f, fClampAngle(turret_horizontal.localEulerAngles.y, _ang_min_horizontal, _ang_max_horizontal), 0f); turret_vertical.rotation = Quaternion.RotateTowards(turret_vertical.rotation, _rot, _vel_vertical * Time.fixedDeltaTime); turret_vertical.localEulerAngles = new Vector3(fClampAngle(turret_vertical.localEulerAngles.x, _ang_min_vertical, _ang_max_vertical), 0f, 0f); } public static float fClampAngle(float angulo, float min, float max) //it clamps an angle without euler angles errors { angulo = Mathf.Repeat(angulo, 360f); return (angulo > 180f) ? Mathf.Max(angulo, 360f+min) : Mathf.Min(angulo, max); }`

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.