我正在使用该教程https://www.youtube.com/watch?v=73Dc5JTCmKI中的脚本,该脚本显示了视野。但是我想反过来说,所以您看不到白色网格的地方将是白色网格,而不是我现在拥有的
如何反转网格,以便在绿色(什么都没有)将成为网格的地方,而在网格的地方将没有网格。
我的脚本:
using UnityEngine;
使用System.Collections; 使用System.Collections.Generic;
公共类FieldOfView:MonoBehaviour {
public float viewRadius;
[Range(0,360)]
public float viewAngle;
public LayerMask targetMask;
public LayerMask obstacleMask;
[HideInInspector]
public List<Transform> visibleTargets = new List<Transform>();
public float meshResolution;
public int edgeResolveIterations;
public float edgeDstThreshold;
public float maskCutawayDst = .1f;
public MeshFilter viewMeshFilter;
Mesh viewMesh;
void Start() {
viewMesh = new Mesh ();
viewMesh.name = "View Mesh";
viewMeshFilter.mesh = viewMesh;
StartCoroutine ("FindTargetsWithDelay", .2f);
}
IEnumerator FindTargetsWithDelay(float delay) {
while (true) {
yield return new WaitForSeconds (delay);
FindVisibleTargets ();
}
}
void LateUpdate() {
DrawFieldOfView ();
}
void FindVisibleTargets() {
visibleTargets.Clear ();
Collider[] targetsInViewRadius = Physics.OverlapSphere (transform.position, viewRadius, targetMask);
for (int i = 0; i < targetsInViewRadius.Length; i++) {
Transform target = targetsInViewRadius [i].transform;
Vector3 dirToTarget = (target.position - transform.position).normalized;
if (Vector3.Angle (transform.forward, dirToTarget) < viewAngle / 2) {
float dstToTarget = Vector3.Distance (transform.position, target.position);
if (!Physics.Raycast (transform.position, dirToTarget, dstToTarget, obstacleMask)) {
visibleTargets.Add (target);
}
}
}
}
void DrawFieldOfView() {
int stepCount = Mathf.RoundToInt(viewAngle * meshResolution);
float stepAngleSize = viewAngle / stepCount;
List<Vector3> viewPoints = new List<Vector3> ();
ViewCastInfo oldViewCast = new ViewCastInfo ();
for (int i = 0; i <= stepCount; i++) {
float angle = transform.eulerAngles.y - viewAngle / 2 + stepAngleSize * i;
ViewCastInfo newViewCast = ViewCast (angle);
if (i > 0) {
bool edgeDstThresholdExceeded = Mathf.Abs (oldViewCast.dst - newViewCast.dst) > edgeDstThreshold;
if (oldViewCast.hit != newViewCast.hit || (oldViewCast.hit && newViewCast.hit && edgeDstThresholdExceeded)) {
EdgeInfo edge = FindEdge (oldViewCast, newViewCast);
if (edge.pointA != Vector3.zero) {
viewPoints.Add (edge.pointA);
}
if (edge.pointB != Vector3.zero) {
viewPoints.Add (edge.pointB);
}
}
}
viewPoints.Add (newViewCast.point);
oldViewCast = newViewCast;
}
int vertexCount = viewPoints.Count + 1;
Vector3[] vertices = new Vector3[vertexCount];
int[] triangles = new int[(vertexCount-2) * 3];
vertices [0] = Vector3.zero;
for (int i = 0; i < vertexCount - 1; i++) {
vertices [i + 1] = transform.InverseTransformPoint(viewPoints [i]) + Vector3.forward * maskCutawayDst;
if (i < vertexCount - 2) {
triangles [i * 3] = 0;
triangles [i * 3 + 1] = i + 1;
triangles [i * 3 + 2] = i + 2;
}
}
viewMesh.Clear ();
viewMesh.vertices = vertices;
viewMesh.triangles = triangles;
viewMesh.RecalculateNormals ();
}
EdgeInfo FindEdge(ViewCastInfo minViewCast, ViewCastInfo maxViewCast) {
float minAngle = minViewCast.angle;
float maxAngle = maxViewCast.angle;
Vector3 minPoint = Vector3.zero;
Vector3 maxPoint = Vector3.zero;
for (int i = 0; i < edgeResolveIterations; i++) {
float angle = (minAngle + maxAngle) / 2;
ViewCastInfo newViewCast = ViewCast (angle);
bool edgeDstThresholdExceeded = Mathf.Abs (minViewCast.dst - newViewCast.dst) > edgeDstThreshold;
if (newViewCast.hit == minViewCast.hit && !edgeDstThresholdExceeded) {
minAngle = angle;
minPoint = newViewCast.point;
} else {
maxAngle = angle;
maxPoint = newViewCast.point;
}
}
return new EdgeInfo (minPoint, maxPoint);
}
ViewCastInfo ViewCast(float globalAngle) {
Vector3 dir = DirFromAngle (globalAngle, true);
RaycastHit hit;
if (Physics.Raycast (transform.position, dir, out hit, viewRadius, obstacleMask)) {
return new ViewCastInfo (true, hit.point, hit.distance, globalAngle);
} else {
return new ViewCastInfo (false, transform.position + dir * viewRadius, viewRadius, globalAngle);
}
}
public Vector3 DirFromAngle(float angleInDegrees, bool angleIsGlobal) {
if (!angleIsGlobal) {
angleInDegrees += transform.eulerAngles.y;
}
return new Vector3(Mathf.Sin(angleInDegrees * Mathf.Deg2Rad),0,Mathf.Cos(angleInDegrees * Mathf.Deg2Rad));
}
public struct ViewCastInfo {
public bool hit;
public Vector3 point;
public float dst;
public float angle;
public ViewCastInfo(bool _hit, Vector3 _point, float _dst, float _angle) {
hit = _hit;
point = _point;
dst = _dst;
angle = _angle;
}
}
public struct EdgeInfo {
public Vector3 pointA;
public Vector3 pointB;
public EdgeInfo(Vector3 _pointA, Vector3 _pointB) {
pointA = _pointA;
pointB = _pointB;
}
}
}
我知道我必须对三角形进行一些更改,但是我不知道如何设置它们。
vertices [0] = Vector3.zero;
for (int i = 0; i < vertexCount - 1; i++) {
vertices [i + 1] = transform.InverseTransformPoint(viewPoints [i]) + Vector3.forward * maskCutawayDst;
if (i < vertexCount - 2) {
triangles [i * 3] = 0;
triangles [i * 3 + 1] = i + 1;
triangles [i * 3 + 2] = i + 2;
}
}
viewMesh.Clear ();
viewMesh.vertices = vertices;
viewMesh.triangles = triangles;
viewMesh.RecalculateNormals ();
对不起,但是我不知道如何解释它。
编辑 所以我仍然有一些问题。 您的解决方案对我不起作用。首先,没有“ circleRadius”,因此我使用viewRadius代替了它。其次,它使我一直争论不休。我的代码进行了一些更改,如下所示:
int vertexCount = viewPoints.Count + 1;
var vertices = new Vector3[vertexCount];
var triangles = new int[(vertexCount - 2) * 3];
vertices[0] = Vector3.zero;
for (int i = 0; i < vertexCount - 1; i++)
{
vertices[i + 1] = transform.InverseTransformPoint(viewPoints[i]);
if (i < vertexCount - 2)
{
triangles[i * 3] = 0;
triangles[i * 3 + 1] = i + 1;
triangles[i * 3 + 2] = i + 2;
}
}
所以在这种情况下,我应该将其更改为? :
int vertexCount = viewPoints.Count + 1;
Vector3[] vertices = new Vector3[(vertexCount) * 2];
int[] triangles = new int[(vertexCount) * 6];
for (int i = 0; i < (vertexCount - 1) * 2; i += 2)
{
vertices[i] = transform.InverseTransformPoint(viewPoints[i]);
vertices[i + 1] = Vector3.Normalize(viewPoints[i]) * viewRadius;
}
for (int i = 0; i < (vertexCount - 3) * 2; i += 1)
{
triangles[i * 6 + 0] = i * 4;
triangles[i * 6 + 1] = i * 4 + 1;
triangles[i * 6 + 2] = i * 4 + 2;
triangles[i * 6 + 3] = i * 4 + 1;
triangles[i * 6 + 4] = i * 4 + 2;
triangles[i * 6 + 5] = i * 4 + 3;
}
所以我更改了代码,没关系,但是当我在播放模式下对其进行测试时,它会给我错误:
ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
FieldOfViews.DrawFieldOfView () (at Assets/_Game/FieldOfView.cs:111)
并且在线:
vertices[i] = transform.InverseTransformPoint(viewPoints[i]) + Vector3.forward * maskCutawayDst;
当我出于测试目的删除该通道时,也会在以下位置出现相同的错误
:vertices[i + 1] = Vector3.Normalize(viewPoints[i]) * circleRadius;
我不知道这是否会引起问题,但是我的maskCutawayDst为0.1,而circleRadius为15。
答案 0 :(得分:2)
使用代码:
int vertexCount = viewPoints.Count + 1;
Vector3[] vertices = new Vector3[vertexCount];
int[] triangles = new int[(vertexCount-2) * 3];
vertices [0] = Vector3.zero;
for (int i = 0; i < vertexCount - 1; i++) {
vertices [i + 1] = transform.InverseTransformPoint(viewPoints [i]) + Vector3.forward * maskCutawayDst;
if (i < vertexCount - 2) {
triangles [i * 3] = 0;
triangles [i * 3 + 1] = i + 1;
triangles [i * 3 + 2] = i + 2;
}
}
更改为
int vertexCount = viewPoints.Count + 1;
Vector3[] vertices = new Vector3[(vertexCount) * 2];
int[] triangles = new int[(vertexCount) * 6];
for (int i = 0; i < vertexCount; i++)
{
Vector3 vertex = transform.InverseTransformPoint(viewPoints[(i == viewPoints.Count) ? 0 : i]);
vertices[i * 2] = vertex;
vertices[i * 2 + 1] = vertex.normalized * viewRadius;
}
for (int i = 0; i < (vertexCount); i++)
{
int j = (vertexCount - 1 == i) ? 0 : i;
triangles[i * 6 + 0] = j * 2 + 0;
triangles[i * 6 + 1] = j * 2 + 1;
triangles[i * 6 + 2] = j * 2 + 2;
triangles[i * 6 + 3] = j * 2 + 1;
triangles[i * 6 + 4] = j * 2 + 3;
triangles[i * 6 + 5] = j * 2 + 2;
}
说明:
图1:正在发生的事情
第一个程序在红色区域创建了一个三角形。这是在中间和两条相交的光线之间(与红线相交)。为了“逆转”,我们必须将两条线作为四边形以固定距离连接到外部点。向量被标准化为具有单位长度,然后与所有点相乘以具有固定距离。 这是通过代码完成的
for (int i = 0; i < vertexCount; i++)
{
Vector3 vertex = transform.InverseTransformPoint(viewPoints[(i == viewPoints.Count) ? 0 : i]);
vertices[i * 2] = vertex;
vertices[i * 2 + 1] = vertex.normalized * viewRadius;
}
然后将这些顶点变成两个三角形(代表一个正方形)。使用以下代码。会创建绿色区域。
for (int i = 0; i < (vertexCount); i++)
{
int j = (vertexCount - 1 == i) ? 0 : i;
triangles[i * 6 + 0] = j * 2 + 0;
triangles[i * 6 + 1] = j * 2 + 1;
triangles[i * 6 + 2] = j * 2 + 2;
triangles[i * 6 + 3] = j * 2 + 1;
triangles[i * 6 + 4] = j * 2 + 3;
triangles[i * 6 + 5] = j * 2 + 2;
}