Advertisement
SebastianLague

Untitled

Jun 12th, 2016
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.07 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4.  
  5. public class FieldOfView : MonoBehaviour {
  6.  
  7.     public float viewRadius;
  8.     [Range(0,360)]
  9.     public float viewAngle;
  10.  
  11.     public LayerMask targetMask;
  12.     public LayerMask obstacleMask;
  13.  
  14.     [HideInInspector]
  15.     public List<Transform> visibleTargets = new List<Transform>();
  16.  
  17.     public float meshResolution;
  18.     public int edgeResolveIterations;
  19.     public float edgeDstThreshold;
  20.  
  21.     Transform viewMeshTransform;
  22.     public MeshFilter viewMeshFilter;
  23.     Mesh viewMesh;
  24.  
  25.     void Start() {
  26.         viewMesh = new Mesh ();
  27.         viewMesh.name = "View Mesh";
  28.         viewMeshFilter.mesh = viewMesh;
  29.         viewMeshTransform = viewMeshFilter.transform;
  30.  
  31.         StartCoroutine ("FindTargetsWithDelay", .2f);
  32.     }
  33.  
  34.  
  35.     IEnumerator FindTargetsWithDelay(float delay) {
  36.         while (true) {
  37.             yield return new WaitForSeconds (delay);
  38.             FindVisibleTargets ();
  39.         }
  40.     }
  41.  
  42.     void LateUpdate() {
  43.         DrawFieldOfView ();
  44.     }
  45.  
  46.     void FindVisibleTargets() {
  47.         visibleTargets.Clear ();
  48.         Collider[] targetsInViewRadius = Physics.OverlapSphere (viewMeshTransform.position, viewRadius, targetMask);
  49.  
  50.         for (int i = 0; i < targetsInViewRadius.Length; i++) {
  51.             Transform target = targetsInViewRadius [i].transform;
  52.             Vector3 dirToTarget = (target.position - viewMeshTransform.position).normalized;
  53.             dirToTarget = new Vector3 (dirToTarget.x, 0, dirToTarget.z);
  54.             if (Vector3.Angle (transform.forward, dirToTarget) < viewAngle / 2) {
  55.                 float dstToTarget = Vector3.Distance (viewMeshTransform.position, target.position);
  56.                 if (!Physics.Raycast (viewMeshTransform.position, dirToTarget, dstToTarget, obstacleMask)) {
  57.                     visibleTargets.Add (target);
  58.                 }
  59.             }
  60.         }
  61.     }
  62.  
  63.     void DrawFieldOfView() {
  64.         int stepCount = Mathf.RoundToInt(viewAngle * meshResolution);
  65.         float stepAngleSize = viewAngle / stepCount;
  66.         List<Vector3> viewPoints = new List<Vector3> ();
  67.         ViewCastInfo oldViewCast = new ViewCastInfo ();
  68.         for (int i = 0; i <= stepCount; i++) {
  69.             float angle = transform.eulerAngles.y - viewAngle / 2 + stepAngleSize * i;
  70.             ViewCastInfo newViewCast = ViewCast (angle);
  71.  
  72.             if (i > 0) {
  73.                 bool edgeDstThresholdExceeded = Mathf.Abs (oldViewCast.dst - newViewCast.dst) > edgeDstThreshold;
  74.                 if (oldViewCast.hit != newViewCast.hit || (oldViewCast.hit && newViewCast.hit && edgeDstThresholdExceeded)) {
  75.                     EdgeInfo edge = FindEdge (oldViewCast, newViewCast);
  76.                     if (edge.pointA != Vector3.zero) {
  77.                         viewPoints.Add (edge.pointA);
  78.                     }
  79.                     if (edge.pointB != Vector3.zero) {
  80.                         viewPoints.Add (edge.pointB);
  81.                     }
  82.                 }
  83.  
  84.             }
  85.  
  86.  
  87.             viewPoints.Add (newViewCast.point);
  88.             oldViewCast = newViewCast;
  89.         }
  90.  
  91.         int vertexCount = viewPoints.Count + 1;
  92.         Vector3[] vertices = new Vector3[vertexCount];
  93.         int[] triangles = new int[(vertexCount-2) * 3];
  94.  
  95.         vertices [0] = Vector3.zero;
  96.         for (int i = 0; i < vertexCount - 1; i++) {
  97.             vertices [i + 1] = viewMeshTransform.InverseTransformPoint(viewPoints [i]);
  98.  
  99.             if (i < vertexCount - 2) {
  100.                 triangles [i * 3] = 0;
  101.                 triangles [i * 3 + 1] = i + 1;
  102.                 triangles [i * 3 + 2] = i + 2;
  103.             }
  104.         }
  105.  
  106.         viewMesh.Clear ();
  107.  
  108.         viewMesh.vertices = vertices;
  109.         viewMesh.triangles = triangles;
  110.         viewMesh.RecalculateNormals ();
  111.     }
  112.  
  113.  
  114.     EdgeInfo FindEdge(ViewCastInfo minViewCast, ViewCastInfo maxViewCast) {
  115.         float minAngle = minViewCast.angle;
  116.         float maxAngle = maxViewCast.angle;
  117.         Vector3 minPoint = Vector3.zero;
  118.         Vector3 maxPoint = Vector3.zero;
  119.  
  120.         for (int i = 0; i < edgeResolveIterations; i++) {
  121.             float angle = (minAngle + maxAngle) / 2;
  122.             ViewCastInfo newViewCast = ViewCast (angle);
  123.  
  124.             bool edgeDstThresholdExceeded = Mathf.Abs (minViewCast.dst - newViewCast.dst) > edgeDstThreshold;
  125.             if (newViewCast.hit == minViewCast.hit && !edgeDstThresholdExceeded) {
  126.                 minAngle = angle;
  127.                 minPoint = newViewCast.point;
  128.             } else {
  129.                 maxAngle = angle;
  130.                 maxPoint = newViewCast.point;
  131.             }
  132.         }
  133.  
  134.         return new EdgeInfo (minPoint, maxPoint);
  135.     }
  136.  
  137.  
  138.     ViewCastInfo ViewCast(float globalAngle) {
  139.         Vector3 dir = DirFromAngle (globalAngle, true);
  140.         RaycastHit hit;
  141.  
  142.         if (Physics.Raycast (viewMeshTransform.position, dir, out hit, viewRadius, obstacleMask)) {
  143.             return new ViewCastInfo (true, hit.point, hit.distance, globalAngle);
  144.         } else {
  145.             return new ViewCastInfo (false, viewMeshTransform.position + dir * viewRadius, viewRadius, globalAngle);
  146.         }
  147.     }
  148.  
  149.     public Vector3 DirFromAngle(float angleInDegrees, bool angleIsGlobal) {
  150.         if (!angleIsGlobal) {
  151.             angleInDegrees += transform.eulerAngles.y;
  152.         }
  153.         return new Vector3(Mathf.Sin(angleInDegrees * Mathf.Deg2Rad),0,Mathf.Cos(angleInDegrees * Mathf.Deg2Rad));
  154.     }
  155.  
  156.     public struct ViewCastInfo {
  157.         public bool hit;
  158.         public Vector3 point;
  159.         public float dst;
  160.         public float angle;
  161.  
  162.         public ViewCastInfo(bool _hit, Vector3 _point, float _dst, float _angle) {
  163.             hit = _hit;
  164.             point = _point;
  165.             dst = _dst;
  166.             angle = _angle;
  167.         }
  168.     }
  169.  
  170.     public struct EdgeInfo {
  171.         public Vector3 pointA;
  172.         public Vector3 pointB;
  173.  
  174.         public EdgeInfo(Vector3 _pointA, Vector3 _pointB) {
  175.             pointA = _pointA;
  176.             pointB = _pointB;
  177.         }
  178.     }
  179.  
  180. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement