Field View 2D
Determinates if a Contact Point belongs to a drawed field view in a plane using just the Collider 2D.
Determinates if a Contact Point belongs to a drawed field view in a plane using just the Collider 2D.
using UnityEngine; | |
/// <summary> | |
/// Field View. | |
/// | |
/// <para> | |
/// Determinates if a point belongs to a drawable field view in 2D. | |
/// </para> | |
/// | |
/// <para> By Javier García | @jvrgms | 2019 </para> | |
/// </summary> | |
[System.Serializable] | |
public struct FieldView2D { | |
#region Class Members | |
public Vector2 offset; // Offset from the center. | |
public float magnitude; // Magnitude of the field of view. | |
[Range (0, 360)] | |
public float angle; // Angle of direction according to Vector.righ. | |
[Range (0, 360)] | |
public float aperture; // Aperture of the field of view. | |
public Color color; // Color to draw the field of view. | |
#endregion | |
#region Public Static Accesors | |
/// <summary> Gets a Field View 2D for top. </summary> | |
/// <value> The Top Field View 2D. </value> | |
public static FieldView2D Top { | |
get { | |
return new FieldView2D () { | |
offset = Vector2.up, | |
magnitude = 1f, | |
angle = 90, | |
aperture = 60, | |
color = Color.grey | |
}; | |
} | |
} | |
/// <summary> Gets a Field View 2D for Bottom. </summary> | |
/// <value> The Bottom Field View 2D. </value> | |
public static FieldView2D Bottom { | |
get { | |
return new FieldView2D () { | |
offset = Vector2.down, | |
magnitude = 1f, | |
angle = 270, | |
aperture = 60, | |
color = Color.grey | |
}; | |
} | |
} | |
/// <summary> Gets a Field View 2D for right. </summary> | |
/// <value> The Right Field View 2D. </value> | |
public static FieldView2D Right { | |
get { | |
return new FieldView2D () { | |
offset = Vector2.right, | |
magnitude = 1f, | |
angle = 0, | |
aperture = 60, | |
color = Color.grey | |
}; | |
} | |
} | |
/// <summary> Gets a Field View 2D for Left. </summary> | |
/// <value> The Left Field View 2D. </value> | |
public static FieldView2D Left { | |
get { | |
return new FieldView2D () { | |
offset = Vector2.left, | |
magnitude = 1f, | |
angle = 180, | |
aperture = 60, | |
color = Color.grey | |
}; | |
} | |
} | |
#endregion | |
#region Drawing Methods | |
/// <summary> Draw the field view at the specified position. </summary> | |
/// <param name="position">Position.</param> | |
public void Draw (Vector2 position) { | |
#if UNITY_EDITOR | |
// TODO: Replace the guidelines for an arc. | |
int n = 8; // Number of guide lines to simulate an abanico. | |
float half = angle - aperture * 0.5f; | |
float segment = aperture / n; | |
for (int i = 0; i <= n; i++) { | |
float alpha = (half + (i * segment)) * Mathf.Deg2Rad; | |
// Getting the start and end of the guide line. | |
Vector2 start = position + offset; | |
Vector2 end = start + magnitude * new Vector2 ( | |
x: Mathf.Cos (alpha), | |
y: Mathf.Sin (alpha) | |
); | |
Gizmos.color = color; | |
Gizmos.DrawLine (start, end); | |
} | |
#endif | |
} | |
#endregion | |
#region Struct Implementation | |
/// <summary> Defines if the field view contains the gived point. </summary> | |
/// <returns>The contains.</returns> | |
/// <param name="point">Point.</param> | |
public bool Contains (Vector2 point) { | |
Vector2 portedPoint = point - offset; | |
if (portedPoint.magnitude > magnitude) | |
return false; | |
float alpha = Mathf.Atan2 (portedPoint.y, portedPoint.x); | |
float gamma = angle - (alpha * Mathf.Rad2Deg) + (aperture * 0.5f); | |
while (gamma >= 360) | |
gamma -= 360; | |
while (gamma <= -360) | |
gamma += 360; | |
return gamma > 0 && gamma <= aperture; | |
} | |
#endregion | |
} |
using UnityEngine; | |
/// <summary> | |
/// Field View 2D Test. | |
/// | |
/// <para> | |
/// Script to test the field view 2D structure in a game object. | |
/// </para> | |
/// | |
/// <para> By Javier García | @jvrgms | 2019 </para> | |
/// </summary> | |
[RequireComponent (typeof (Collider2D))] | |
public class FieldView2DTest: MonoBehaviour { | |
#region Class Methods | |
// Parameters to read physics. | |
[Space, Header ("Physic Inputs")] | |
[SerializeField] | |
private FieldView2D topView = FieldView2D.Top; | |
[SerializeField] | |
private FieldView2D bottomView = FieldView2D.Bottom; | |
[SerializeField] | |
private FieldView2D rightView = FieldView2D.Right; | |
[SerializeField] | |
private FieldView2D leftView = FieldView2D.Left; | |
// Bools to track walls and surfaces. | |
[SerializeField] | |
protected bool facingTop, facingBottom, facingRight, facingLeft; | |
private new Collider2D collider; // Collider attached. | |
private ContactPoint2D[] contacts; // Array to store contacts. | |
private int contactCounter; // Number of contact points. | |
private readonly int contactsLimit = 10; // Limit of contact points. | |
#endregion | |
#region MonoBehaviour Methods | |
// Called on inspector to draw gizmos. | |
private void OnDrawGizmos () { | |
topView.Draw (transform.position); | |
bottomView.Draw (transform.position); | |
rightView.Draw (transform.position); | |
leftView.Draw (transform.position); | |
} | |
// Called on awake. | |
private void Awake () { | |
collider = GetComponent<Collider2D> (); | |
contacts = new ContactPoint2D[contactsLimit]; | |
} | |
// Update is called once per frame | |
private void Update () { | |
ReadInputPhysics (); | |
} | |
#endregion | |
#region Class Implementation | |
// Method to read physics interactions. | |
private void ReadInputPhysics () { | |
contactCounter = collider.GetContacts (contacts); | |
facingTop = facingBottom = facingLeft = facingRight = false; | |
for (int i = 0; i < contactCounter; i++) { | |
Vector2 point = transform.InverseTransformPoint (contacts[i].point); | |
facingTop |= topView.Contains (point); | |
facingBottom |= bottomView.Contains (point); | |
facingRight |= rightView.Contains (point); | |
facingLeft |= leftView.Contains (point); | |
} | |
} | |
#endregion | |
} |