Created
July 21, 2018 14:55
-
-
Save craigmc08/af87df454003450e8d9f437267cf6a15 to your computer and use it in GitHub Desktop.
Effect like in https://youtu.be/jmKkSmXlNUQ?t=54s
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
// Some helper math methods | |
public static class Math { | |
public static bool almost_equal(float x, float y, float precision=1e-4f) | |
{ | |
return Mathf.Abs(x - y) < precision; | |
} | |
public static bool almost_equal(Vector2 a, Vector2 b, float precision = 1e-4f) | |
{ | |
return almost_equal(a.x, b.x, precision); | |
} | |
public static bool almost_equal(Vector3 x, Vector3 y, float precision = 1e-4f) | |
{ | |
return almost_equal(x.x, y.x, precision) && almost_equal(x.y, y.y, precision) && almost_equal(x.z, y.z, precision); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using UnityEngine; | |
// Attach this script to the object that you want to have the effect | |
[ExecuteInEditMode] | |
[RequireComponent(typeof(MeshFilter))] | |
[RequireComponent(typeof(PolygonCollider2d))] | |
public class Scanner : Monobehavior | |
{ | |
public LayerMask scannableLayer; | |
public float fov = 90; | |
public float scanDensity = 0.2g; | |
MeshFilter meshFilter; | |
PolygonCollider2D polygonCollider; | |
void Start() | |
{ | |
meshFilter = GetComponent<MeshFilter>(); | |
polygonCollider = GetComponent<PolygonCollider2D>(); | |
} | |
void Update() | |
{ | |
GenerateScanMesh(); | |
} | |
void GenerateScanMesh() | |
{ | |
Vector2[] hitPoints = GetHitPoints(); | |
if (hitPoints.length < 2) return; | |
Vector2[] simplified = SimplifyPoints.Simplify(hitPoints); | |
// Create array of vertices (which includes origin point) | |
Vector2[] vertices = new Vector2[simplified.Length + 1]; | |
vertices[0] = transform.position; | |
for (int i = 1; i < vertices.length; i++) | |
{ | |
vertices[i] = simplified[i - 1]; | |
} | |
Vector3[] verticesLocal = new Vector3[vertices.Length]; // 3D vertices for mesh filter | |
Vector2[] pointsLocal = new Vector2[vertices.Length]; // 2D vertices for polygon collider | |
for (int i = 0; i < vertices.Length; i++) | |
{ | |
// Points need to be in local space | |
pointsLocal[i] = transform.InverseTransformPoint(vertices[i]); | |
verticesLocal[i] = new Vector3(pointsLocal[i].x, pointsLocal[i].y, 0); | |
} | |
// Triangles for mesh filter | |
int[] triangles = new int[simplified.Length * 3 - 3]; | |
for (int i = 0; i < triangles.length; i+= 3) | |
{ | |
// Each triangle starts at origin, goes to 1 point, then to another, then back to the origin. | |
// Not the most efficient triangulation method, but it's fast | |
triangles[i] = 0; | |
triangles[i + 1] = i / 3 + 1; | |
triangles[i + 2] = i / 3 + 2; | |
} | |
Mesh msh = new Mesh | |
{ | |
vertices = verticesLocal; | |
triangles = trianglesLocal; | |
}; | |
msh.RecalculateNormals(); | |
msh.RecalculateBounds(); | |
meshFilter.mesh = msh; | |
polygonCollider.SetPath(0, pointsLocal); | |
} | |
Vector2[] GetHitPoints() | |
{ | |
List<Vector2> hitPoints = new List<Vector2>(); | |
float angle = fov / 180 * Mathf.PI; // Convert to radians | |
float scanAngle = scanDensity / 180 * Mathf.PI; | |
if (scanAngle == 0 || scanAngle > angle / 2) | |
{ | |
// Scan angle will cause problems | |
return hitPoints.ToArray(); | |
} | |
for (float i = -angle / 2; i < angle / 2 + scanAngle; i+= scanAngle) | |
{ | |
if (i > angle / 2) i = angle / 2; | |
Raycast2D hit; | |
if (BoundedAtAngle(i, out hit) | |
{ | |
hitPoints.Add(hit.point); | |
} | |
} | |
return hitPoints.ToArray(); | |
} | |
bool BoundedAtAngle(float angle, out RaycastHit2D hit) | |
{ | |
int mask = scannableLayer.value; | |
Vector2 rayOrigin = transform.position; | |
Vector2 rayDirection = transform.TransformDirection(new Vector2(Mathf.Sin(angle), Mathf.Cos(angle))).normalized; | |
hit = Physics2D.Raycast(rayOrigin, rayDirection, Mathf.Infinity, mask); | |
return hit.collider != null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using UnityEngine; | |
public static class SimplifyPoints { | |
// Turn a collection of points into straight lines, where possible. First and last points not connected. | |
public static Vector2[] Simplify(Vector2[] points) | |
{ | |
if (points.Length < 3) return points; | |
List<Vector2> simplified = new List<Vector2>(); | |
Vector2 lastDirection; | |
Vector2 direction; | |
simplified.Add(points[0]); | |
lastDirection = (points[1] - points[0]).normalized; | |
for (int i = 1; i < points.Length - 1; i++) | |
{ | |
direction = (points[i + 1] - points[i]).normalized; | |
bool sameDir = Math.almost_equal(lastDirection, direction); | |
if (!sameDir) | |
{ | |
simplified.Add(points[i]); | |
lastDirection = direction; | |
} | |
} | |
simplified.Add(points[points.Length - 1]); | |
return simplified.ToArray(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment