# How to detect when an object is within an arc?

I’m having an issue trying to detect an object within an arc. What I’m trying to do is, after setting a minimum and maximum angle, detect an object that falls within that range. When I put in angle values like -60 degrees to 60 degrees, it works fine. When I put in a value that’s 180 degrees (-90 to 90), my calculated Forward vector gets set to 0 (because I’m calculating a vector between the 2 angles), and when it’s greater than 180 degrees, the detection becomes flipped.

Below are examples.

Red Lines = Detection Arc.

Green Line = Forward Axis.

Cyan Line = Detected Target.

[148525-arcbug.png*_|148525]

And here is the code:

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MountedTurret : MonoBehaviour
{
[System.Serializable]
public class Turret
{
[SerializeField]
Vector3 _localPosition;

[SerializeField]
float _angleMin = -90;

[SerializeField]
float _angleMax = 90;

public float Range = 10f;

public float AngleMin(Transform t)
{
return _angleMin + t.eulerAngles.y;
}

public float AngleMax(Transform t)
{
return _angleMax + t.eulerAngles.y;
}

public Vector3 Position(Transform t)
{
return t.position + _localPosition;
}

public Vector3 Forward(Transform t)
{
var position = Position(t);

float aMin = AngleMin(t);
float aMax = AngleMax(t);

return ((vMin + vMax) * 0.5f).normalized;
}

public bool IsInRange(Transform t, Vector3 point)
{
var position = Position(t);
float dist = Vector3.Distance(position, point);
if(dist <= Range)
{
var direction = point - position;
float angle = Vector3.Angle(Forward(t), direction);
if(angle >= AngleMin(t) && angle <= AngleMax(t))
{
return true;
}
}
return false;
}
}

public Ship ship;
public Turret[] turrets;
public Transform test;

public void OnDrawGizmos()
{
const int segments = 5;
List<Vector2> arcPoints = new List<Vector2>();
float angle;
float arcLength;
Vector3 position;
foreach (Turret t in turrets)
{
position = t.Position(transform);
Gizmos.color = Color.green;
Debug.Log("My Forward is: " + t.Forward(transform));
Gizmos.DrawRay(position, t.Forward(transform) * t.Range);
angle = t.AngleMin(transform);
arcLength = t.AngleMax(transform) - angle;
for (int i = 0; i <= segments; i++)
{
float x = Mathf.Sin(Mathf.Deg2Rad * angle) * t.Range;
float y = Mathf.Cos(Mathf.Deg2Rad * angle) * t.Range;

angle += (arcLength / segments);
}
//TODO Draw the arc
Gizmos.color = Color.red;
var arcPos = new Vector3(position.x + arcPoints.x, position.y, position.z + arcPoints.y);
var prevPos = arcPos;
Gizmos.DrawLine(position, arcPos);
//TODO For
for(int i = 0; i < arcPoints.Count; ++i)
{
arcPos = new Vector3(position.x + arcPoints_.x, position.y, position.z + arcPoints*.y);*_
``````

Gizmos.DrawLine(prevPos, arcPos);
prevPos = arcPos;
}
arcPos = new Vector3(position.x + arcPoints[arcPoints.Count - 1].x, position.y, position.z + arcPoints[arcPoints.Count - 1].y);
Gizmos.DrawLine(position, arcPos);
}
}

// Update is called once per frame
void Update()
{
foreach (Turret t in turrets)
{
if(t.IsInRange(transform, test.position))
{
Debug.DrawLine(t.Position(transform), test.position, Color.cyan);
}
}
}
}

_*

Hey there,

take a look at this tutorial.

Do a projection as explained by the link and you geet a value that will indicate if your object is in the front or the back when the value “c” is positive/negative.

Let me know if that was too unclear and i can try to help you a bit more specifically.

Thanks to Captain_Pineapple, I was able to figure out the answer, by converting my 2 angles into 2 planes!

Here is the revised IsInRange function, as well as 2 Plane generation functions:

``````public Plane MinPlane(Transform t)
{
var position = Position(t);

float aMin = AngleMin(t);

Vector3 normal =  Vector3.Cross(vMin, Vector3.down);

return new Plane(normal, position);
}

public Plane MaxPlane(Transform t)
{
var position = Position(t);

float aMax = AngleMax(t);

Vector3 normal =  Vector3.Cross(vMax, Vector3.up);

return new Plane(normal, position);
}

public bool IsInRange(Transform t, Vector3 point)
{
var position = Position(t);
float dist = Vector3.Distance(position, point);
if(dist <= Range)
{
var minP = MinPlane(t);
var maxP = MaxPlane(t);
var direction = point - position;

if(Vector3.Dot(minP.normal, direction) > 0 || Vector3.Dot(maxP.normal, direction) > 0)
{
return true;
}
}
return false;
}
``````