private static Vector2[] GetCorners(Collider2D c) { if (c is BoxCollider2D box) { Vector2 size = box.size * 0.5f; return(new Vector2[4] { box.transform.TransformPoint(new Vector3(size.x, size.y)), box.transform.TransformPoint(new Vector3(-size.x, size.y)), box.transform.TransformPoint(new Vector3(size.x, -size.y)), box.transform.TransformPoint(new Vector3(-size.x, -size.y)) }); } if (c is CircleCollider2D circle) { float radius = circle.radius; var results = new List <Vector2>(); for (int i = 0; i < 360; i += 10) { results.Add(circle.transform.TransformPoint(Vector2Utils.FromAngle(i) * radius)); //Debug.DrawLine(Vector3.zero, Vector2Utils.FromAngle(i) * radius, Color.white, 20f); } return(results.ToArray()); } return(new Vector2[0]); }
public static List <Vector2> GetPointsInArc(float fovAngle, float fovDistance, float offsetAngle, Vector2 origin, int resolution) { var results = new List <Vector2>(); float startAngle = offsetAngle + fovAngle * 0.5f; for (int i = 0; i <= resolution; i++) { float angle = startAngle - i * (fovAngle / resolution); results.Add(Vector2Utils.FromAngle(angle) * fovDistance + origin); } return(results); }
public static List <Vector2> GetFilteredPoints(float fovAngle, float fovDistance, float offsetAngle, Vector2 origin) { var results = new List <Vector2>(); var forward = Vector2Utils.FromAngle(offsetAngle); float distanceSqr = fovDistance * fovDistance; float halfAngle = fovAngle * 0.5f; foreach (var p in ObstacleManager.Corners) { Vector2 direction = (p - origin); if (Vector2.Angle(direction, forward) < halfAngle && direction.sqrMagnitude < distanceSqr) { results.Add(p); } } return(results); }
/// <summary> /// Gets global points of FOV /// </summary> /// <param name="fovAngle">angle of field of view (degrees)</param> /// <param name="fovDistance">distance of field of view</param> /// <param name="resolution">Resolution in rays per degree</param> /// <param name="offsetAngle">rotation of object in degress (0 means facing right, 90 means up)</param> /// <param name="origin">origin of field of view</param> /// <returns>list of global points</returns> public static List <Vector3> GetPointsFromFOV(float fovAngle, float fovDistance, float resolution, float offsetAngle, Vector2 origin, LayerMask mask) { var results = new List <Vector3>(); var arcPoints = GetPointsInArc(fovAngle, fovDistance, offsetAngle, origin, Mathf.RoundToInt(fovAngle * resolution)); var corners = GetFilteredPoints(fovAngle, fovDistance, offsetAngle, origin); var forward = Vector2Utils.FromAngle(offsetAngle); bool[] arcHits = new bool[arcPoints.Count]; // Getting all points along the arc for (int i = 0; i < arcPoints.Count; i++) { Vector2 p = arcPoints[i]; results.Add(Raycast(origin, (p - origin).normalized, fovDistance, mask, out bool hitted)); arcHits[i] = hitted; } // Getting all points for corners foreach (var c in corners) { Vector2 dir = (c - origin).normalized; AddByAngle(origin, forward, results, Raycast(origin, Quaternion.Euler(0, 0, 0.05f) * dir, fovDistance, mask, out bool hitted)); AddByAngle(origin, forward, results, Raycast(origin, dir, fovDistance, mask, out hitted)); AddByAngle(origin, forward, results, Raycast(origin, Quaternion.Euler(0, 0, -0.05f) * dir, fovDistance, mask, out hitted)); } for (int i = 0; i < arcHits.Length - 1; i++) { if (arcHits[i] != arcHits[i + 1]) { Vector2 edgePoint; bool hit; if (!arcHits[i] && arcHits[i + 1]) { // Edge to right of arc Point i edgePoint = Raycast(arcPoints[i], arcPoints[i + 1] - arcPoints[i], Vector2.Distance(arcPoints[i], arcPoints[i + 1]), mask, out hit); } else { // Edge to left of arc Point i + 1 edgePoint = Raycast(arcPoints[i + 1], arcPoints[i] - arcPoints[i + 1], Vector2.Distance(arcPoints[i], arcPoints[i + 1]), mask, out hit); } if (!hit) { continue; } Vector2 hitPoint = Raycast(origin, edgePoint - origin, Vector2.Distance(origin, edgePoint), mask, out hit); if (hit) { AddByAngle(origin, forward, results, hitPoint); } else { AddByAngle(origin, forward, results, edgePoint); } } } return(results); }