Advertisement
Guest User

Untitled

a guest
Jun 24th, 2019
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.90 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3.  
  4.  
  5. public class FieldOfView : MonoBehaviour
  6. {
  7.     public float viewRadius;
  8.     [Range(0, 360)]
  9.     public float viewAngle;
  10.  
  11.     public LayerMask obstacleMask;
  12.     public MeshFilter viewMeshFilter;
  13.  
  14.     public float meshResolution;
  15.     public int edgeResolveIterations;
  16.     public float edgeDstThreshold;
  17.     public float maskCutawayDst = .1f;
  18.  
  19.     Mesh viewMesh;
  20.     List<Vector3> viewPoints = new List<Vector3>();
  21.     Vector3 edgeMinPoint, edgeMaxPoint;
  22.  
  23.     void Start()
  24.     {
  25.         viewMesh = new Mesh();
  26.         viewMesh.name = "View Mesh";
  27.         viewMeshFilter.mesh = viewMesh;
  28.     }
  29.  
  30.     private void Update()
  31.     {
  32.        
  33.             var mouseWorldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
  34.  
  35.             transform.rotation = Quaternion.LookRotation(Vector3.forward, (mouseWorldPosition - transform.position).normalized);
  36.        
  37.     }
  38.        
  39.  
  40.     void LateUpdate()
  41.     {//draw field of view
  42.  
  43.        
  44.             int stepCount = Mathf.RoundToInt(viewAngle * meshResolution);
  45.             float stepAngleSize = viewAngle / stepCount;
  46.             viewPoints.Clear();
  47.             ViewCastInfo oldViewCast = new ViewCastInfo();
  48.             for (int i = 0; i <= stepCount; i++)
  49.             {
  50.                 float angle = -transform.eulerAngles.z - viewAngle / 2 + stepAngleSize * i;
  51.                 ViewCastInfo newViewCast = ViewCast(angle);
  52.  
  53.                 if (i > 0)
  54.                 {
  55.                     bool edgeDstThresholdExceeded = Mathf.Abs(oldViewCast.dst - newViewCast.dst) > edgeDstThreshold;
  56.                     if (oldViewCast.hit != newViewCast.hit || (oldViewCast.hit && newViewCast.hit && edgeDstThresholdExceeded))
  57.                     {
  58.                         FindEdge(oldViewCast, newViewCast, out edgeMinPoint, out edgeMaxPoint);
  59.                         if (edgeMinPoint != Vector3.zero)
  60.                             viewPoints.Add(edgeMinPoint);
  61.                         if (edgeMaxPoint != Vector3.zero)
  62.                             viewPoints.Add(edgeMaxPoint);
  63.                     }
  64.  
  65.                 }
  66.  
  67.                 viewPoints.Add(newViewCast.point);
  68.                 oldViewCast = newViewCast;
  69.             }
  70.  
  71.             int vertexCount = viewPoints.Count + 1;
  72.             Vector3[] vertices = new Vector3[vertexCount];
  73.             int[] triangles = new int[(vertexCount - 2) * 3];
  74.  
  75.             vertices[0] = Vector3.zero;
  76.             for (int i = 0; i < vertexCount - 1; i++)
  77.             {
  78.                 vertices[i + 1] = transform.InverseTransformPoint(viewPoints[i]) + Vector3.up * maskCutawayDst;
  79.  
  80.                 if (i < vertexCount - 2)
  81.                 {
  82.                     triangles[i * 3] = 0;
  83.                     triangles[i * 3 + 1] = i + 1;
  84.                     triangles[i * 3 + 2] = i + 2;
  85.                 }
  86.             }
  87.  
  88.             viewMesh.Clear();
  89.  
  90.             viewMesh.vertices = vertices;
  91.             viewMesh.triangles = triangles;
  92.             viewMesh.RecalculateNormals();
  93.        
  94.        
  95.     }
  96.  
  97.     void FindEdge(ViewCastInfo minViewCast, ViewCastInfo maxViewCast, out Vector3 minPoint, out Vector3 maxPoint)
  98.     {
  99.         float minAngle = minViewCast.angle;
  100.         float maxAngle = maxViewCast.angle;
  101.         minPoint = Vector3.zero;
  102.         maxPoint = Vector3.zero;
  103.  
  104.         for (int i = 0; i < edgeResolveIterations; i++)
  105.         {
  106.             float angle = (minAngle + maxAngle) / 2;
  107.             ViewCastInfo newViewCast = ViewCast(angle);
  108.  
  109.             bool edgeDstThresholdExceeded = Mathf.Abs(minViewCast.dst - newViewCast.dst) > edgeDstThreshold;
  110.             if (newViewCast.hit == minViewCast.hit && !edgeDstThresholdExceeded)
  111.             {
  112.                 minAngle = angle;
  113.                 minPoint = newViewCast.point;
  114.             }
  115.             else
  116.             {
  117.                 maxAngle = angle;
  118.                 maxPoint = newViewCast.point;
  119.             }
  120.         }
  121.     }
  122.  
  123.     ViewCastInfo ViewCast(float globalAngle)
  124.     {
  125.         Vector3 dir = DirFromAngle(globalAngle);
  126.         var hit = Physics2D.Raycast(transform.position, dir, viewRadius, obstacleMask);
  127.  
  128.         if (hit)
  129.             return new ViewCastInfo(true, hit.point, hit.distance, globalAngle);
  130.  
  131.         return new ViewCastInfo(false, transform.position + dir * viewRadius, viewRadius, globalAngle);
  132.     }
  133.  
  134.     public Vector3 DirFromAngle(float angleInDegrees)
  135.     {
  136.         return new Vector3(Mathf.Sin(angleInDegrees * Mathf.Deg2Rad), Mathf.Cos(angleInDegrees * Mathf.Deg2Rad), 0);
  137.     }
  138.  
  139.     public struct ViewCastInfo
  140.     {
  141.         public bool hit;
  142.         public Vector3 point;
  143.         public float dst;
  144.         public float angle;
  145.  
  146.         public ViewCastInfo(bool _hit, Vector3 _point, float _dst, float _angle)
  147.         {
  148.             hit = _hit;
  149.             point = _point;
  150.             dst = _dst;
  151.             angle = _angle;
  152.         }
  153.     }
  154. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement